# -*-perl-*-
# vim: set filetype=perl:
######################################################################
# File: texi2html.pm
#
# Default values for command-line arguments and for various customizable
# procedures are set in this file.
#
# A copy of this file is pasted into the beginning of texi2html by
# running './configure'.
#
# Copy this file, rename it and make changes to it, if you like.
# Afterwards, load the file with command-line 
# option --init-file <your_init_file>
#
# This file is in the public domain. Thus it may easily be used as an 
# example for further customizations.
#
# Originally written by Olaf Bachmann in 2000.
#
# Those values may be overrided by values set in $sysconfdir/texi2html/Config 
# and then by values set in $HOME/texi2html/Config.
#
# $Id$


##################################################################
# The following variables can also be set by command-line options
#
# command line switches may override these values, and values set in files
# specified by --init-file are also taken into account.
#
# options common with makeinfo
# -I
# add a directory to the list of directories where @include files are
# searched for (besides the directory of the file). additional '-I' 
# args are appended to this list.
# (APA: Don't implicitely search ., to conform with the docs!)
# my @INCLUDE_DIRS = (".");

use strict;

@INCLUDE_DIRS = ();

# -P
# prepend a directory to the list of directories where @include files are
# searched for before the directory of the file. additional '-P' 
# args are prepended to this list.
@PREPEND_DIRS = ();

# --split section|chapter|node|none
# if $SPLIT is set to 'section' (resp. 'chapter') one html file per section 
# (resp. chapter) is generated. If $SPLIT is set to 'node' one html file per 
# node or sectioning element is generated. In all these cases separate pages 
# for Top, Table of content (Toc), Overview and About are generated.
# Otherwise a monolithic html file that contains the whole document is 
# created.
set_default('SPLIT', '');

# --separated-footnotes
# if this is set footnotes are on a separated page. Otherwise they are at
# the end of each file (if the document is split).
set_default('footnotestyle', 'end');

# --fill-column
set_default('FILLCOLUMN', 72);

# --number | --no-number
# if this is set the sections are numbered, and section names and numbers 
# are used in references and menus (instead of node names).
set_default('NUMBER_SECTIONS', 1);

# --headers
# if this is set then navigation panels are printed at the beginning of each 
# section.
# If the document is split at nodes then navigation panels are 
# printed at the end if there were more than WORDS_IN_PAGE words on page.
#
# Navigation panels are always printed at the beginning of output files.
#
# This is most useful if you do not want to have section navigation
# with --split chapter. There will be chapter navigation panel at the 
# beginning and at the end of chapters anyway.
# this is mostly not used in the default case, important for html.
set_default('HEADERS', 0);

# -o filename
# If this is set a monolithic document is outputted into $filename.
set_default('OUT', undef);
set_default('OUTFILE', undef);

# --split-size
# if undef, the info output is not split
set_default('SPLIT_SIZE', 300000);

# --internal-links
set_default('INTERNAL_LINKS', undef);

# --no-validate
# suppress node cross-reference validation
set_default('novalidate', 0);

# --documentlanguage
# use gdt('my string') if you want to have translations of 'my string'.
# Translations are in texinfo/po_document/
# This is used for the initial language, it is overriden during 
# document processing if there is a @documentlanguage.
# It is ignored if the language is passed on the command line.
set_default('documentlanguage', 'en');

# --transliterate-file-names 
# transliterate node names for external refs (and internal if NODE_FILES)
set_default('TRANSLITERATE_FILE_NAMES', 1);

# --error-limit
# quit after NUM errors (default 100).
set_default('ERROR_LIMIT', 100);

# --css-include
# All the specified css files are used. More precisely the @import sections
# are added to the beginning of the CSS_LINES the remaining is added at
# the end of the CSS_LINES (after the css rules generated by the program).
# cf texinfo manual for more info.
# - means STDIN
@CSS_FILES = ();

# --css-ref
# the specified url are used as stylesheet links
@CSS_REFS = ();

# --paragraph-indent
set_default('paragraphindent',3);

# --enable-encoding
set_default('ENABLE_ENCODING', 0);

# --force
set_default('FORCE', 0);

# --no-warn
set_default('NO_WARN', 0);

# --number-footnotes
set_default('NUMBER_FOOTNOTES', 1);

# --batch
set_default('BATCH', 0);

# --silent/--quiet
set_default('SILENT', 0);

# --Xopt
@TEXI2DVI_ARGUMENTS = ();

# not in makeinfo but in texi2dvi
# --command
@COMMANDS = ();

##################################################################
# option specific of texi2html
# --debug
# The integer value specifies what kind of debugging output is generated.
set_default('DEBUG', 0);

# --doctype
# The value is the 'SystemLiteral' which identifies the canonical DTD 
# for the document.
# Definition: The SystemLiteral is called the entity's system
# identifier. It is a URI, which may be used to retrieve the entity.
# See http://www.xml.com/axml/target.html#NT-ExternalID
set_default('DOCTYPE', '');

# --frameset-doctype
# When frames are used, this SystemLiteral identifies the DTD used for
# the file containing the frame description.
set_default('FRAMESET_DOCTYPE', '');

# --test
# If this value is true, some variables which should be dynamically generated 
# (the date, the user running texi2html, the version of texi2html) are set to 
# fix and given values. This is usefull in case the resulting manual is 
# compared with a reference. For example this is used in the tests.
set_default('TEST', 0);

# --dump-texi
# This value is usefull for debugging purposes. The result of the first pass is
# put in <document name>.passtexi, the result of the second pass is put in 
# <document name>.passfirst.
set_default('DUMP_TEXI', 0);

# --expand
# the @EXPAND array contains the expanded section names.
@EXPAND = ();

# --iso
# if this value is true, ISO8859 characters are used for quotes.
# --iso does more than what USE_ISO does.
set_default('USE_ISO', 0);

# --conf-dir
# append to the files searched for init files.
@CONF_DIRS = ();

# --top-file
# This file name is used for the top-level file.
# The extension is set appropriately, if necessary.
# If empty, <basename of document>.html is used.
# Typically, you would set this to "index.html".
set_default('TOP_FILE', '');

# --toc-file
# This file name is used for the table of contents.  The
# extension is set appropriately, if necessary.
# If empty, <basename of document>_toc.html is used.
set_default('TOC_FILE', '');

# --frames
# if the value is true, HTML 4.0 "frames" are used. 
# A file describing the frame layout is generated, together with a file 
# with the short table of contents.
set_default('FRAMES', 0);

# --menu | --no-menu
# if the value is true the Texinfo menus are shown.
# this is defined in all the formats
set_default('SHOW_MENU', 1);

# --use-nodes
# if this is set the nodes are used as sectioning elements. 
# Otherwise the nodes are incorporated in sections.
set_default('USE_NODES', 1);

# --node-files
# if this is set one file per node is generated, which can be a target for 
# cross manual references.
set_default('NODE_FILES', undef);

# --toc-links
# if this is set, links from headings to toc entries are created.
set_default('TOC_LINKS', 0);

# --subdir
# If this is set, then put result files into the specified directory.
# If not set, then result files are put into the current directory.
#$SUBDIR = 'html';
set_default('SUBDIR', undef);

# --short-extn
# If this is set, then all HTML files will have extension ".htm" instead of
# ".html". This is helpful when shipping the document to DOS-based systems.
set_default('SHORTEXTN', 0);

# --prefix
# This set the output file prefix, prepended to all .html, .gif and .pl files.
# By default, this is the basename of the document.
set_default('PREFIX', '');

# --short-ref
# if this is set cross-references are given without section.
set_default('SHORT_REF', 1);

# --idx-sum
# if value is set, then for each @printindex <index name>
# <document name>_<index name>.idx is created which contains lines of the form
# key ref sorted alphabetically (case matters).
set_default('IDX_SUMMARY', 0);

# --def-table
# If this is set a table construction for @def.... instead of definition 
# lists.
# (New Option: 27.07.2000 Karl Heinz Marbaise)
set_default('DEF_TABLE', 0);

# --verbose
# if this is set chatter about what we are doing.
set_default('VERBOSE', '');

# --ignore-preamble-text
# If this is set the text before @node and sectioning commands is ignored.
set_default('IGNORE_PREAMBLE_TEXT', 0);

# --html-xref-prefix
# base directory for external manuals. Obsolete.
set_default('EXTERNAL_DIR', undef);

# --l2h
# if this is set, latex2html is used for generation of math content.
set_default('L2H', '');

# --monolithic
# output only one file including ToC. It only makes sense when not split
set_default('MONOLITHIC', 1);

######################
# The following options are only relevant if $L2H is set
#
# --l2h-l2h
# name/location of latex2html program
set_default('L2H_L2H', 'latex2html');

# --l2h-skip
# If this is set the actual call to latex2html is skipped. The previously
# generated content is reused, instead.
# If set to 0, the cache is not used.
# If undef the cache is used for as many tex fragments as possible
# and for the remaining the command is run.
set_default('L2H_SKIP', undef);

# --l2h-tmp
# If this is set l2h uses the specified directory for temporary files. The path
# leading to this directory may not contain a dot (i.e., a ".");
# otherwise, l2h will fail.
set_default('L2H_TMP', '');
 
# --l2h-file
# If set, l2h uses the file as latex2html init file
set_default('L2H_FILE', undef);

# --l2h-clean
# if this is set the intermediate files generated by texi2html in relation with
# latex2html are cleaned (they all have the prefix <document name>_l2h_).
set_default('L2H_CLEAN', 1);

##############################################################################
#
# The following can only be set in the init file
#
##############################################################################

@INPUT_FILE_SUFFIXES = ('.txi','.texinfo','.texi','.txinfo','');

set_default('firstparagraphindent', 'none');

@T2H_FORMAT_EXPAND = ('plaintext');

# In file encoding. The @documentencoding allows autodetection of 
# that variable.
set_default('documentencoding', undef);

# In file encoding, understandable by perl. Set according to documentencoding
set_default('IN_ENCODING', undef);

# Formatted document encoding name. If undef, set in init_out based on 
# OUT_ENCODING or documentencoding if they are defined
set_default('ENCODING_NAME', undef);

# Out files encoding, understandable by perl. If undef, set in init_out
# using ENCODING_NAME or IN_ENCODING if they are defined
set_default('OUT_ENCODING', undef);

# if undef set to @documentdescription. If there is no @documentdescription,
# set in page_head.
set_default('documentdescription', undef);

# EXTERNAL_CROSSREF_SPLIT at the document level set to 1 if SPLIT, 
# to 0 otherwise
set_default('EXTERNAL_CROSSREF_SPLIT', undef);

# output as @today, and also as the date. Set automatically if not set
# otherwise.
set_default('today', undef);

# simple headers formatting, not in a table and using node names.
set_default('HEADER_IN_TABLE', 0);

# output the generation date in the header.
set_default('DATE_IN_HEADER', 0);

# use table for indentation of complex formats
set_default('COMPLEX_FORMAT_IN_TABLE', 0);

# if set, node names are used to construct file names
# if undef, it is set if split at node, or NODE_FILES is set.
set_default('NODE_FILENAMES', undef);

# If true do table of contents even if there is no @content
set_default('contents', undef);

# If true do short table of contents even if there is no @shortcontent
set_default('shortcontents', undef);

# set by @setcontentsaftertitlepage/@setshortcontentsaftertitlepage
set_default('setcontentsaftertitlepage', undef);
set_default('setshortcontentsaftertitlepage', undef);

# corresponds with @kbdinputstyle
set_default('kbdinputstyle', 'distinct');

# corresponds with @frenchspacing
set_default('frenchspacing', 'off');

# correspond with @allowcodebreaks
set_default('allowcodebreaks', 'true');

# corresponds with @setfilename. Set with caution.
set_default('setfilename', undef);

# if unset, don't show a title
set_default('SHOW_TITLE', 1);

# if set style is added in attribute.
set_default('INLINE_CSS_STYLE', 0);

# if set, no css is used.
set_default('NO_CSS', 0);

# if set, the image files are completed to be relative from the
# document directory, to the source manual directory and then to
# the image
set_default('COMPLETE_IMAGE_PATHS', 0);

# if true, begin outputting at @setfilename, if this command is present.
set_default('IGNORE_BEFORE_SETFILENAME', 1);

# if true the link in Overview link to the corresponding Toc entry.
set_default('OVERVIEW_LINK_TO_TOC', 1);

# if set, use node anchors for sections targets
set_default('USE_NODE_TARGET', 1);

# new style for crossrefs
set_default('NEW_CROSSREF_STYLE', 1);

# top heading is always at the beginning of the element.
# FIXME looks like a no-op
set_default('TOP_HEADING_AT_BEGINNING', 0);

# use titlepage for the title instead of a simplest title
set_default('USE_TITLEPAGE_FOR_TITLE', 0);

# used as identation for block enclosing command @example, etc
# If not empty, must be enclosed in <td></td>
$EXAMPLE_INDENT_CELL = '';

# same as above, only for @small
$SMALL_EXAMPLE_INDENT_CELL = '';

# unused
$SMALL_FONT_SIZE = '-1';

# horizontal rules
# not used
$SMALL_RULE = '';
$MIDDLE_RULE = '';
# used in html
$DEFAULT_RULE = '';
$BIG_RULE = '';

# output the program name in the footer
set_default('PROGRAM_NAME_IN_FOOTER', 0);

# if non-empty, and no @..heading appeared in Top node, then
# use this as header for top node/section, otherwise use value of
# @settitle or @shorttitle (in that order)
$TOP_HEADING = '';

# if set, use this chapter for 'Index' button, else
# use first chapter with @printindex
$INDEX_CHAPTER = '';

set_default('SIMPLE_MENU', 1);

set_default('OPEN_QUOTE_SYMBOL', '`');
set_default('CLOSE_QUOTE_SYMBOL', "'");

$NO_NUMBER_FOOTNOTE_SYMBOL = '*';

# if true put a $MENU_SYMBOL before unnumbered in menus
$UNNUMBERED_SYMBOL_IN_MENU = 0;

# extension for nodes files when NODE_FILES is true
set_default('NODE_FILE_EXTENSION', 'txt');	    

# extension
set_default('EXTENSION', 'txt');

# file name used for Top node when NODE_FILES is true
#TOP_NODE_FILE = 'index';
set_default('TOP_NODE_FILE', undef);

# file name used for Top node in references
set_default('TOP_NODE_FILE_TARGET', 'index');

# file used as document basename, when input file is -
$STDIN_DOCU_NAME = 'stdin';

# file used as document output basename, when output file is -
$STDOUT_DOCU_NAME = 'stdout';

# node name used for Top node when automatic node directions are used
set_default('TOP_NODE_UP', '(dir)');

# this controls the pre style for menus
$MENU_PRE_STYLE = 'font-family: serif';

# on bug-texinfo is has been said the the style is not code_style
# for menus (except for the node name).
# this controls the menu preformatted format
# FIXME this is not dynamic, so change in MENU_PRE_STYLE is not taken 
# into account.
# This is used if the menu appears within a preformatted format (which
# is certainly an invalid construct), and SIMPLE_MENU is not set.
$MENU_PRE_COMPLEX_FORMAT = {
              'class' => 'menu-preformatted',
#              'style' => 'code'
   };

# This controls the ul style for toc
$NO_BULLET_LIST_STYLE = '';
$NO_BULLET_LIST_ATTRIBUTE = '';

# These lines are inserted before and after the shortcontents 
$BEFORE_OVERVIEW = "";
$AFTER_OVERVIEW = "";

# These lines are inserted before and after the contents 
$BEFORE_TOC_LINES = "";
$AFTER_TOC_LINES = "";

# text inserted after <body ...>
$AFTER_BODY_OPEN = '';

# text inserted before </body>, this will be automatically inside <p></p>
$PRE_BODY_CLOSE = '';

# this is added inside <head></head> after <title> and some <meta name>
# stuff, it can be used for eg. <style>, <script>, <meta> etc. tags.
$EXTRA_HEAD = '';

# Specifies the minimum page length required before a navigation panel
# is placed at the bottom of a page 
# FIXME this is not true:
# THIS_WORDS_IN_PAGE holds number of words of current page
set_default('WORDS_IN_PAGE', 300);

# if this is set a vertical navigation panel is used.
set_default('VERTICAL_HEAD_NAVIGATION', 0);

# html version for latex2html
set_default('L2H_HTML_VERSION', "4.0");

# use icons.
set_default('ICONS', 0);

# use old framework for translations
set_default('I18N_PERL_HASH', 0);

# command name to invoke when used as a texi2dvi wrapper
set_default('TEXI2DVI', 'texi2dvi');

# this resets some defaults, those that are also set in formats and
# not set in every formats.
#
# this is called below after %default_style_map_texi is defined
sub t2h_default_set_variables_default()
{
  $CAPTION_STYLE = 'strong';

# if this variable is true, @setfilename is used if found to determine the
# out file name
  set_default('USE_SETFILENAME', 1);

# if true, use the filename and extension from setfilename. For Info.
  set_default('USE_SETFILENAME_EXTENSION', 0);

# FIXME is this right?
# default used in init_out for the setting of the ENCODING_NAME variable
  set_default('DEFAULT_ENCODING', 'utf8');

# if set and menu entry equals menu description, then do not print 
# menu description.
# Likewise, if node name equals entry name, do not print entry name.
  set_default('AVOID_MENU_REDUNDANCY', 0);

# if true, use the original command if the result is an entity
  set_default('ENABLE_ENCODING_USE_ENTITY', 0);

# if set, output the contents where the command is located
# This is ignored if set*contentsaftertitlepage is set
  set_default('INLINE_CONTENTS', 1);

# if set, do redirection files for renamed nodes
  set_default('RENAMED_NODES_REDIRECTIONS', undef);

# if set, do about
  set_default('DO_ABOUT', 0);

# symbol put at the beginning of nodes entry in menu (and optionnaly of 
# unnumbered in menus, see UNNUMBERED_SYMBOL_IN_MENU variable)
  $MENU_SYMBOL = '*';

# symbol put at the end of nodes entry in menu
  $MENU_ENTRY_COLON = ':';

# symbol put at the end of index entries
  $INDEX_ENTRY_COLON = ':';

# if set, then use node names in menu entries, instead of section names
  set_default('NODE_NAME_IN_MENU', 1);

# if set always separate description and menu link, even in 
# preformatted environment
  set_default('SEPARATE_DESCRIPTION', 0);

# try up sections to complete the node directions
  set_default('USE_UP_FOR_ADJACENT_NODES', 0);

# use accesskey in hrefs
  set_default('USE_ACCESSKEY', 1);

# use rel= and rev= in hrefs. Currently only rel is used
  set_default('USE_REL_REV', 1);

# generate <link> elements in head
  set_default('USE_LINKS', 1);

# if this variable is true, numeric entities are used when there is no
# corresponding textual entity.
  set_default('USE_NUMERIC_ENTITY', 0);

# if set and SPLIT is set, then split index pages at the next letter
# after they have more than that many entries
  set_default('SPLIT_INDEX', 0);

# extensions used for images
  @IMAGE_EXTENSIONS = ('png','jpg', 'txt');

  set_default('USE_NODES', 1);

  set_default('USE_SECTIONS', 1);

# also set by command line options
  set_default('footnotestyle', 'end');

  set_default('DOCTYPE', '');

  set_default('USE_ISO', 0);

  set_default('NUMBER_SECTIONS', 1);
  
  set_default('TOP_FILE', '');

  set_default('ENABLE_ENCODING', 0);

#
# Formatting functions
#
# They will be reset here between formats switch
# if they are defined in this function.
#

# these are more or less the documented vanilla versions, so they
# are reset
$unknown           = \&t2h_default_unknown;
$unknown_style     = \&t2h_default_unknown_style;
$external_ref      = \&t2h_default_external_ref;
$internal_ref      = \&t2h_default_internal_ref;
$tab_item_texi     = \&t2h_default_tab_item_texi;
$complex_format    = \&t2h_default_complex_format;
$toc_body          = \&T2H_DEFAULT_toc_body;
$misc_command_line = \&t2h_default_misc_command_line;
$misc_command_line_texi = \&t2h_default_misc_command_line;
$print_title               = \&T2H_DEFAULT_print_title;
# reset in info and xml
$element_heading = \&t2h_default_element_heading;
# reset in html
$inline_contents    = \&T2H_DEFAULT_inline_contents;
# reset in docbook and info.
$style                    = \&T2H_GPL_style;
$format                   = \&T2H_GPL_format;
# reset in info
$simple_command             = \&t2h_default_simple_command;
# reset in info
$thing_command              = \&t2h_default_thing_command;
# reset in html and xml
$caption_shortcaption     = \&t2h_default_caption_shortcaption;
$caption_shortcaption_command  = \&t2h_default_caption_shortcaption_command;
# reset in docbook and xml. Not really vanilla, but documented.
$printindex        = \&t2h_GPL_default_printindex;
# reset by xml and html
$misc_element_label         = \&t2h_default_misc_element_label;
# set in html
$init_out    = \&t2h_default_init_out;
# set in info and xml
$paragraph_style_command  = \&t2h_default_paragraph_style_command;
# set in info
$colon_command            = \&t2h_default_colon_command;
# set in docbook
$quotation_prepend_text   = \&t2h_default_quotation_prepend_text;
# set in info
$copying_comment = \&t2h_default_copying_comment;

# set in html and info
$print_section            = \&T2H_DEFAULT_print_section;

# set in docbook and xml
%colon_command_punctuation_characters = (
   '.' => '.',
   ':' => ':',
   '?' => '?',
   '!' => '!'
);



# in info
$footnote_texi = undef;
$begin_paragraph_texi = undef;
$begin_style_texi = undef;
$begin_special_region = undef;
$end_special_region = undef;
$empty_preformatted = undef;

%line_command_map = (
       'title'    => '',
       'subtitle' => '',
       'author'   => '',
);

%format_in_paragraph = (
);
# map mapping css specification to style

%css_map = 
     (
     );

@text_substitutions_normal = ();
@text_substitutions_texi = ();
@text_substitutions_simple_format = ();
@text_substitutions_pre = ();

%region_formats_kept = ();

%style_map_texi = ();
t2h_default_copy_style_map (\%default_style_map_texi, \%style_map_texi);

# reset in info
%simple_map_texi = %default_simple_map;

# modified in docbook
%special_accents = (
      'ringaccent' => 'aA',
      "'"          => 'aeiouyAEIOUY',
      ','          => 'cC',
      '^'          => 'aeiouAEIOU',
      '`'          => 'aeiouAEIOU',
      '~'          => 'nNaoAO',
      '"'          => 'aeiouyAEIOU',
# according to http://www2.lib.virginia.edu/small/vhp/download/ISO.txt
# however this doesn't seems to work in firefox
#      'ogonek'     => 'aeiuAEIU',
);

# modified by info, xml, docbook
# %no_paragraph_commands should not be reset since it has been 
# filled with defaults for many other commands.

# FIXME this prevents the user from setting those entries.
$no_paragraph_commands{'cindex'} = 1;
$no_paragraph_commands{'float'} = 1;
delete $no_paragraph_commands{'anchor'};

# modified in docbook and xml
%stop_paragraph_command = (
 'titlefont' => 1,
 'insertcopying' => 1,
 'sp' => 1,
 'verbatiminclude' => 1,
 'page' => 1,
# FIXME they also stop preformatted, so cannot be here.
# 'printindex' => 1,
# 'listoffloats' => 1
);

}

sub t2h_default_raw_text_load()
{
  set_default('SPLIT', '');
  # extension for nodes files when NODE_FILES is true
  set_default('NODE_FILE_EXTENSION', 'txt');	    

  # extension
  set_default('EXTENSION', 'txt');
  @T2H_FORMAT_EXPAND = ('plaintext');
  set_default('USE_TITLEPAGE_FOR_TITLE', 0);
  set_default('HEADERS', 0);
  set_default('SIMPLE_MENU', 1);
  set_default('INLINE_INSERTCOPYING', 0);
  # reset here, in case it was set to something else by another
  # format.
  set_default('TOP_NODE_FILE', undef);

  %simple_map = %default_simple_map;
  %simple_map_pre = %simple_map;

  %things_map = %default_things_map;
  %pre_map = %things_map;

  %style_map = ();
  %style_map_pre = ();
  t2h_default_copy_style_map (\%default_style_map, \%style_map);
  t2h_default_copy_style_map (\%default_style_map_pre, \%style_map_pre);

  # could also be t2h_default_set_iso_symbols()
  t2h_remove_text_substitutions("'", 1, 0, 0, 1);
  t2h_remove_text_substitutions('`', 1, 0, 0, 1);
  set_default('OPEN_QUOTE_SYMBOL', '`');
  set_default('CLOSE_QUOTE_SYMBOL', "'");

  $BEFORE_OVERVIEW = "";
  $AFTER_OVERVIEW = "";

  $BEFORE_TOC_LINES = "";
  $AFTER_TOC_LINES = "";


  foreach my $complex_format ('example', 'smallexample', 'display',
  'smalldisplay', 'lisp', 'smalllisp', 'format', 'smallformat',
  'menu', 'detailmenu', 'direntry', 'menu_comment')
  {
    $complex_format_map{$complex_format}->{'begin'} = '';
    $complex_format_map{$complex_format}->{'end'} = '';
  }

  %format_map = (
#       'quotation'   =>  'blockquote',
       # lists
#       'itemize'     =>  'ul',
       'enumerate'   =>  '',
#       'multitable'  =>  'table',
       'table'       =>  '',
       'vtable'      =>  '',
       'ftable'      =>  '',
       'group'       =>  '',
       'raggedright'       =>  '',
#       'detailmenu'  =>  '',
       );

  #
  # Controls the layout
  #

  $print_page_head              = \&T2H_DEFAULT_print_page_head;
  $contents                 = \&T2H_DEFAULT_contents;
  $shortcontents            = \&T2H_DEFAULT_shortcontents;
  $one_section              = \&T2H_DEFAULT_one_section;
  $print_Top                = \&T2H_DEFAULT_print_Top;
  $print_Top_footer             = \&T2H_DEFAULT_print_Top_footer;
  $print_misc_header            = \&T2H_DEFAULT_print_misc_header;
  $print_misc_footer            = \&T2H_DEFAULT_print_misc_footer;
  $print_section_footer     = \&T2H_DEFAULT_print_section_footer;
  $print_chapter_header     = \&T2H_DEFAULT_print_chapter_header;
  $print_section_header     = \&T2H_DEFAULT_print_section_header;
  $print_chapter_footer     = \&T2H_DEFAULT_print_chapter_footer;
  $print_page_foot              = \&T2H_DEFAULT_print_page_foot;
  $print_head_navigation    = \&T2H_DEFAULT_print_head_navigation;
  $print_foot_navigation    = \&T2H_DEFAULT_print_foot_navigation;
  $end_section              = \&T2H_DEFAULT_end_section;
  # changed in info
  $print_Footnotes              = \&T2H_DEFAULT_print_Footnotes;
  # used if split
  $about_body                 = \&T2H_DEFAULT_about_body;
  $print_navigation           = \&T2H_DEFAULT_print_navigation;

  #
  # Controls the formatting
  #

  $empty_line               = \&t2h_default_empty_line;
  $anchor            = \&t2h_default_anchor;
  $anchor_label               = \&t2h_default_anchor_label;
  $image             = \&t2h_default_image;
  $heading           = \&t2h_default_heading;
  $heading_text      = \&t2h_default_heading_text;
  $heading_text_preformatted      = \&t2h_default_heading_text_preformatted;
  $element_label              = \&t2h_default_element_label;
  $index_entry_label = \&t2h_default_index_entry_label;
  #$menu_command      = \&t2h_default_menu_command;
  $menu_link         = \&t2h_default_menu_link;
  #$menu_description  = \&t2h_default_menu_description;
  $paragraph         = \&t2h_default_paragraph;
  $preformatted      = \&t2h_default_preformatted;
  $protect_text      = \&t2h_default_protect_text;
  $normal_text       = \&t2h_default_normal_text;
  $acronym_like             = \&t2h_default_acronym_like;
  $sp                = \&t2h_default_sp;
  $quotation                = \&t2h_default_quotation;
  $table_list        = \&t2h_default_table_list;
  $list_item         = \&t2h_default_list_item;
  $table_line        = \&t2h_default_table_line;
  $table_item        = \&t2h_default_table_item;
  $cell              = \&t2h_default_cell;
  $row               = \&t2h_default_row;
  $def_item          = \&t2h_default_def_item;
  $def               = \&t2h_default_def;
  $def_line          = \&t2h_default_def_line;
  $cartouche         = \&t2h_default_cartouche;
  $raw               = \&t2h_default_raw;
  $format_list_item_texi      = \&t2h_default_format_list_item_texi;
  $print_index       = \&t2h_default_print_index;
  $index_summary     = \&t2h_default_index_summary;
  $index_entry       = \&t2h_default_index_entry;
  $index_letter      = \&t2h_default_index_letter;
  $foot_line_and_ref = \&t2h_default_foot_line_and_ref;
  $foot_section      = \&t2h_default_foot_section;
  $tab_item_texi     = \&t2h_default_tab_item_texi;
  $listoffloats             = \&t2h_default_listoffloats;
  $listoffloats_entry       = \&t2h_default_listoffloats_entry;
  $float                     = \&t2h_default_float;

  t2h_default_set_variables_default();
}

my %things_map_xml;
my %pre_map_xml;

sub t2h_default_set_variables_xml()
{
  t2h_default_set_variables_default();
  set_default('ENABLE_ENCODING_USE_ENTITY', 1);
  set_default('EXTENSION', 'xml');
  t2h_default_set_iso_symbols(1);

  $empty_line = \&t2h_default_empty_line;
  $comment = \&xml_default_comment;
  $line_command = \&xml_default_line_command;
 
  %things_map = %things_map_xml;
  %pre_map = %pre_map_xml;
  %simple_format_texi_map = %pre_map;

  %simple_format_style_map_texi = ();
  t2h_default_copy_style_map (\%default_style_map_texi, \%simple_format_style_map_texi);
  foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
  {
#    $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal'];
    $simple_format_style_map_texi{$accent_command}->{'function'} = \&xml_default_accent;
  }
}

sub t2h_default_set_variables_texi2html()
{
  set_default('USE_SETFILENAME', 0);
  set_default('USE_SETFILENAME_EXTENSION', 0);
  set_default('footnotestyle', 'separate');
  set_default('INLINE_CONTENTS', 0);
  set_default('FORCE', 1);
  set_default('AVOID_MENU_REDUNDANCY', 1);
  set_default('TOP_HEADING_AT_BEGINNING', 1);
  set_default('TOP_FILE', '');
  set_default('USE_ACCESSKEY', 0);
  set_default('NODE_NAME_IN_MENU', 0);
  set_default('OVERVIEW_LINK_TO_TOC', 0);
  set_default('USE_UP_FOR_ADJACENT_NODES', 1);
  set_default('USE_REL_REV', 0);
  set_default('USE_LINKS', 0);
  set_default('USE_NODES', undef);
  set_default('USE_SECTIONS', 1);
  set_default('NODE_FILENAMES', 0);
  set_default('USE_NUMERIC_ENTITY', 1);
  set_default('SPLIT', '');
  set_default('SPLIT_INDEX', 100);
  set_default('PROGRAM_NAME_IN_FOOTER', 1);
  set_default('HEADER_IN_TABLE', 1);
  set_default('SHORT_REF', 0);
  set_default('USE_TITLEPAGE_FOR_TITLE', 1);
  set_default('DO_ABOUT', 1);
  $MENU_ENTRY_COLON = '';
  $INDEX_ENTRY_COLON = '';
  #@LINKS_BUTTONS =
  #  (
  #    'Top', 'Index', 'Contents', 'About', 'Up', 'NextFile', 'PrevFile'
  #  );

  set_default('ENABLE_ENCODING_USE_ENTITY', 1);
}

# specify in this array which "buttons" should appear in which order
# in the navigation panel for sections; use ' ' for empty buttons (space)
@SECTION_BUTTONS =
    (
     'FastBack', 'Back', 'Up', 'Forward', 'FastForward',
     ' ', ' ', ' ', ' ',
     'Top', 'Contents', 'Index', 'About',
    );

# buttons for misc stuff
@MISC_BUTTONS = ('Top', 'Contents', 'Index', 'About');

@TOP_BUTTONS = ( 'Back', 'Forward', ' ','Contents', 'Index', 'About');
#@TOP_BUTTONS = ('Top', 'Contents', 'Index', 'About');


# buttons for chapter file footers
# (and headers but only if HEADERS is false)
@CHAPTER_BUTTONS =
    (
     'FastBack', 'FastForward', ' ',
     ' ', ' ', ' ', ' ',
     'Top', 'Contents', 'Index', 'About',
    );

# buttons for section file footers
@SECTION_FOOTER_BUTTONS =
    (
     'FastBack', 'Back', 'Up', 'Forward', 'FastForward',
    );

@NODE_FOOTER_BUTTONS = @SECTION_BUTTONS;

@LINKS_BUTTONS =
    (
      'Top', 'Index', 'Contents', 'About', 'Up', 'NextFile', 'PrevFile'
    );


# insert here name of icon images for buttons
# Icons are used, if ICONS and resp. value are set
%ACTIVE_ICONS =
    (
     'Top',         '',
     'Contents',    '',
     'Overview',    '',
     'Index',       '',
     'This',        '',
     'Back',        '',
     'FastBack',    '',
     'Prev',        '',
     'Up',          '',
     'Next',        '',
     'NodeUp',      '',
     'NodeNext',    '',
     'NodePrev',    '',
     'NodeForward', '',
     'NodeBack',    '',
     'Forward',     '',
     'FastForward', '',
     'About' ,      '',
     'First',       '',
     'Last',        '',
     'NextFile',    '',
     'PrevFile',    '',
     ' ',           '',
    );

# insert here name of icon images for these, if button is inactive
%PASSIVE_ICONS =
    (
     'Top',         '',
     'Contents',    '',
     'Overview',    '',
     'Index',       '',
     'This',        '',
     'Back',        '',
     'FastBack',    '',
     'Prev',        '',
     'Up',          '',
     'Next',        '',
     'NodeUp',      '',
     'NodeNext',    '',
     'NodePrev',    '',
     'NodeForward', '',
     'NodeBack',    '',
     'Forward',     '',
     'FastForward', '',
     'About',       '',
     'First',       '',
     'Last',        '',
     'NextFile',    '',
     'PrevFile',    '',
    );

%misc_pages_targets = (
   'Overview' => 'SEC_Overview',
   'Contents' => 'SEC_Contents',
   'Footnotes' => 'SEC_Foot',
   'About' => 'SEC_About'
);

# determine the null devices
my $default_null_device = File::Spec->devnull();
%null_device_file = (
 $default_null_device => 1
);
# special case, djgpp recognizes both null devices
if ($Config{osname} eq 'dos' and $Config{osvers} eq 'djgpp')
{
  $null_device_file{'/dev/null'} = 1;
  $null_device_file{'NUL'} = 1;
}

%texi2dvi_formats = (
 'dvi' => 1,
 'pdf' => 1,
 'ps' => 1
);

$finish_out    = \&t2h_default_finish_out;
$translate_names = \&t2h_default_translate_names;

sub t2h_default_translate_names()
{
# Names of text as alternative for icons
# FIXME maybe get those in simple_format?
    %NAVIGATION_TEXT =
    (
     'Top',         gdt('Top'),
     'Contents',    gdt('Contents'),
     'Overview',    gdt('Overview'),
     'Index',       gdt('Index'),
     ' ',           ' ',
     'This',        gdt('Current'),
     'Back',        ' < ',
     'FastBack',    ' << ',
     'Prev',        gdt('Previous'),
     'Up',          gdt('Up'),
     'Next',        gdt('Next'),
     'NodeUp',      gdt('Up'),
     'NodeNext',    gdt('Next'),
     'NodePrev',    gdt('Previous'),
     'NodeForward', gdt('Forward node'),
     'NodeBack',    gdt('Back node'),
     'Forward',     ' > ',
     'FastForward', ' >> ',
     'About',       ' ? ',
     'First',       ' |< ',
     'Last',        ' >| ',
     'NextFile',    gdt('Next file'),
     'PrevFile',    gdt('Previous file'),
    );
    %BUTTONS_TEXT = %NAVIGATION_TEXT;

    %BUTTONS_GOTO =
    (
     'Top',         gdt('Cover (top) of document'),
     'Contents',    gdt('Table of contents'),
     'Overview',    gdt('Short table of contents'),
     'Index',       gdt('Index'),
     'This',        gdt('Current section'),
     'Back',        gdt('Previous section in reading order'),
     'FastBack',    gdt('Beginning of this chapter or previous chapter'),
     'Prev',        gdt('Previous section on same level'),
     'Up',          gdt('Up section'),
     'Next',        gdt('Next section on same level'),
     'NodeUp',      gdt('Up node'),
     'NodeNext',    gdt('Next node'),
     'NodePrev',    gdt('Previous node'),
     'NodeForward', gdt('Next node in node reading order'),
     'NodeBack',    gdt('Previous node in node reading order'),
     'Forward',     gdt('Next section in reading order'),
     'FastForward', gdt('Next chapter'),
     'About' ,      gdt('About (help)'),
     'First',       gdt('First section in reading order'),
     'Last',        gdt('Last section in reading order'),
     'NextFile',    gdt('Forward section in next file'),
     'PrevFile',    gdt('Back section in previous file'),
    );

    %BUTTONS_NAME =
    (
     'Top',         gdt('Top'),
     'Contents',    gdt('Contents'),
     'Overview',    gdt('Overview'),
     'Index',       gdt('Index'),
     ' ',           ' ',
     'This',        gdt('This'),
     'Back',        gdt('Back'),
     'FastBack',    gdt('FastBack'),
     'Prev',        gdt('Prev'),
     'Up',          gdt('Up'),
     'Next',        gdt('Next'),
     'NodeUp',      gdt('NodeUp'),
     'NodeNext',    gdt('NodeNext'),
     'NodePrev',    gdt('NodePrev'),
     'NodeForward', gdt('NodeForward'),
     'NodeBack',    gdt('NodeBack'),
     'Forward',     gdt('Forward'),
     'FastForward', gdt('FastForward'),
     'About',       gdt('About'),
     'First',       gdt('First'),
     'Last',        gdt('Last'),
     'NextFile',    gdt('NextFile'),
     'PrevFile',    gdt('PrevFile'),
    );

}

sub t2h_default_set_iso_symbols($;$$)
{
    my $value = shift;
    my $from_cmd_line = shift;
    my $from_document = shift;
    if ($from_cmd_line)
    {
       main::set_from_cmdline('USE_ISO', $value);
    }
    elsif ($from_document)
    {
       set_from_document('USE_ISO', $value);
    }
    else
    {
       set_default('USE_ISO', $value);
    }
    my ($open_quote, $close_quote);
    if ($value)
    {
       foreach my $association ([\%things_map, \%things_map_xml],
                         [\%pre_map, \%pre_map_xml],
                        [\%simple_format_simple_map_texi, \%pre_map_xml])
       {
          foreach my $thing (keys(%{$association->[0]}))
          {
              if (defined($association->[0]->{$thing}) and $association->[0]->{$thing} !~ /^\&\w+\;$/ and defined($association->[1]->{$thing}) and $association->[1]->{$thing} =~ /^\&\w+\;$/)
              {
                  $association->[0]->{$thing} = $association->[1]->{$thing};
              }
          }
       }
       t2h_add_text_substitutions(["'", '&rsquo;'], 1, 0, 0, 1);
       t2h_add_text_substitutions(['`', '&lsquo;'], 1, 0, 0, 1);
       $open_quote = '&lsquo;';
       $close_quote = '&rsquo;';
    }
    else
    {
       foreach my $association ([\%things_map, \%default_things_map],
                         [\%pre_map, \%default_things_map],
                        [\%simple_format_simple_map_texi, \%default_things_map])
       {
          foreach my $thing (keys(%{$association->[0]}))
          {
              if (defined($association->[0]->{$thing}) and $association->[0]->{$thing} =~ /^\&\w+\;$/ and defined($association->[1]->{$thing}) and $association->[1]->{$thing} !~ /^\&\w+\;$/)
              {
                  $association->[0]->{$thing} = &$protect_text($association->[1]->{$thing});
              }
          }
       }
       t2h_remove_text_substitutions("'", 1, 0, 0, 1);
       t2h_remove_text_substitutions('`', 1, 0, 0, 1);
       $open_quote = '`';
       $close_quote = "'";
    }
    if ($from_cmd_line)
    {
       main::set_from_cmdline('OPEN_QUOTE_SYMBOL', $open_quote);
       main::set_from_cmdline('CLOSE_QUOTE_SYMBOL', $close_quote);
    }
    elsif ($from_document)
    {
       main::set_from_document('OPEN_QUOTE_SYMBOL', $open_quote);
       main::set_from_document('CLOSE_QUOTE_SYMBOL', $close_quote);
    }
    else
    {
       set_default('OPEN_QUOTE_SYMBOL', $open_quote);
       set_default('CLOSE_QUOTE_SYMBOL', $close_quote);
    }
    
}

# is used in main program for dumping texi too.
sub t2h_default_set_out_encoding()
{
    # set in reverse order of precedence, such that later setting
    # override the first settings.
    my $out_encoding_from_documentencoding = main::encoding_alias (get_conf('documentencoding'), undef, 'determining encoding from documentencoding');
    set_from_document('OUT_ENCODING', $out_encoding_from_documentencoding) if (defined($out_encoding_from_documentencoding));
    set_from_document('OUT_ENCODING', get_conf('IN_ENCODING')) if (defined(get_conf('IN_ENCODING')));
    my $out_encoding_from_encoding_name = main::encoding_alias (get_conf('ENCODING_NAME'), undef, 'determining encoding from default encoding');
    set_from_document('OUT_ENCODING', $out_encoding_from_encoding_name) if (defined($out_encoding_from_encoding_name));

    main::document_warn (__("Document encoding is utf8, but there is no unicode support")) if (defined(get_conf('OUT_ENCODING')) and get_conf('OUT_ENCODING') eq 'utf-8' and !get_conf('USE_UNICODE'));

    set_from_document('ENCODING_NAME', 'us-ascii');
    set_from_document('ENCODING_NAME', $perl_charset_to_html{get_conf('DEFAULT_ENCODING')}) if (defined(get_conf('DEFAULT_ENCODING')) and defined($perl_charset_to_html{get_conf('DEFAULT_ENCODING')}));
    set_from_document('ENCODING_NAME', get_conf('documentencoding')) if (defined(get_conf('documentencoding')));
    set_from_document('ENCODING_NAME', get_conf('IN_ENCODING')) if (defined(get_conf('IN_ENCODING')));
    set_from_document('ENCODING_NAME', get_conf('OUT_ENCODING')) if (defined(get_conf('OUT_ENCODING')));
    set_from_document('ENCODING_NAME', $perl_charset_to_html{get_conf('documentencoding')}) if (defined(get_conf('documentencoding')) and defined($perl_charset_to_html{get_conf('documentencoding')}));
    set_from_document('ENCODING_NAME', $perl_charset_to_html{get_conf('IN_ENCODING')}) if (defined(get_conf('IN_ENCODING')) and defined($perl_charset_to_html{get_conf('IN_ENCODING')}));
    set_from_document('ENCODING_NAME', $perl_charset_to_html{get_conf('OUT_ENCODING')}) if (defined(get_conf('OUT_ENCODING')) and defined($perl_charset_to_html{get_conf('OUT_ENCODING')}));


    if (get_conf('VERBOSE'))
    {
       # verbose output
       my $out_encoding = get_conf('OUT_ENCODING');
       $out_encoding = 'UNDEF' if (!defined($out_encoding));
       my $in_encoding = get_conf('IN_ENCODING');
       $in_encoding = 'UNDEF' if (!defined($in_encoding));
       my $document_encoding = get_conf('documentencoding');
       $document_encoding = 'UNDEF' if (!defined($document_encoding));
       my $encoding_name = get_conf('ENCODING_NAME');
       print STDERR "# Encodings: doc $document_encoding, in $in_encoding out $out_encoding, name $encoding_name\n";
    }
}

sub t2h_default_init_out()
{
    &$translate_names;
    # set external cross ref splitting like splitting.
    if (get_conf('SPLIT'))
    {
       set_from_document('EXTERNAL_CROSSREF_SPLIT', 1);
    }
    else
    {
       set_from_document('EXTERNAL_CROSSREF_SPLIT', 0);
    }
}

my %t2h_default_formats_load_table = (
  'html' => \&html_default_load,
  'info' => \&info_default_load,
  'docbook' => \&docbook_default_load,
  'xml' => \&xml_default_load,
  'plaintext' => \&plaintext_default_load,
  'raw-text' => \&t2h_default_raw_text_load,
);

sub t2h_default_load_format($;$)
{
  my $format = shift;
  my $from_command_line = shift;
  if (defined($t2h_default_formats_load_table{$format}) or $texi2dvi_formats{$format})
  {
     $OUTPUT_FORMAT = $format;
     &{$t2h_default_formats_load_table{$format}}($from_command_line) unless ($texi2dvi_formats{$format});
     $Texi2HTML::THISDOC{'format_from_command_line'} = $format if ($from_command_line);
     return 1;
  }
  else
  {
     return 0;
  }
}

sub t2h_encoding_is_entity($)
{
  my $text = shift;
  return 0 if (!get_conf('ENABLE_ENCODING_USE_ENTITY'));
  return 1 if ($text =~ /^&/ and $text =~ /;$/);
}

# this is for info.pm
use vars qw(%t2h_enable_encoding_default_accent);
my @t2h_enable_encoding_accents_stack;
my %t2h_enable_encoding_default_commands;

sub t2h_enable_encoding_load()
{
   t2h_default_push_handler(\&t2h_enable_encoding_init, \@command_handler_names);
   t2h_default_push_handler(\&t2h_enable_encoding_finish, \@command_handler_finish);
   #push @command_handler_process, \&t2h_enable_encoding_init;
   #push @command_handler_finish, \&t2h_enable_encoding_finish;
   foreach my $key (keys(%unicode_accents), 'dotless')
   {
     $t2h_enable_encoding_default_accent{'normal'}->{$key} = $style_map{$key}->{'function'};
     $t2h_enable_encoding_default_accent{'texi'}->{$key} = $style_map_texi{$key}->{'function'};
     $t2h_enable_encoding_default_accent{'pre'}->{$key} = $style_map_pre{$key}->{'function'};
     $style_map{$key}->{'function'} = \&t2h_enable_encoding_normal_accent;
     $style_map_texi{$key}->{'function'} = \&t2h_enable_encoding_texi_accent;
     $style_map_pre{$key}->{'function'} = \&t2h_enable_encoding_pre_accent;
   }
   foreach my $key (%things_map)
   {
     if (exists($unicode_map{$key}) and ($unicode_map{$key} ne ''))
     {
       $t2h_enable_encoding_default_commands{'normal'}->{$key} = $things_map{$key};
       $t2h_enable_encoding_default_commands{'texi'}->{$key} = $texi_map{$key};
       $t2h_enable_encoding_default_commands{'sorting'}->{$key} = $sorting_things_map{$key};
       $t2h_enable_encoding_default_commands{'pre'}->{$key} = $pre_map{$key};
     }
   }
}

sub t2h_enable_encoding_finish()
{
   foreach my $key (%things_map)
   {
     if (exists($unicode_map{$key}) and ($unicode_map{$key} ne ''))
     {
       $things_map{$key} = $t2h_enable_encoding_default_commands{'normal'}->{$key};
       $texi_map{$key} = $t2h_enable_encoding_default_commands{'texi'}->{$key};
       $sorting_things_map{$key} = $t2h_enable_encoding_default_commands{'sorting'}->{$key};
       $pre_map{$key} = $t2h_enable_encoding_default_commands{'pre'}->{$key}; 
     }
   }
}

sub t2h_enable_encoding_init()
{
  if (get_conf('ENCODING_NAME') eq 'utf-8')
  {
    foreach my $key (%things_map)
    {
      if (exists($unicode_map{$key}) and ($unicode_map{$key} ne ''))
      {
        $things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($things_map{$key}));
        $texi_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($texi_map{$key}));
        $sorting_things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($sorting_things_map{$key}));
        $pre_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($pre_map{$key}));
      }
    }
  }
  elsif (exists($makeinfo_encoding_to_map{get_conf('ENCODING_NAME')}))
  {
    my $enc_map = $makeinfo_encoding_to_map{get_conf('ENCODING_NAME')};

    foreach my $key (%things_map)
    {
      if (exists($unicode_map{$key}) and ($unicode_map{$key} ne '') and 
        exists($makeinfo_unicode_to_eight_bit{$enc_map}->{$unicode_map{$key}}))
      { # we let perl handle the conversion
        $things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($things_map{$key}));
        $texi_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($texi_map{$key}));
        $sorting_things_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($sorting_things_map{$key}));
        $pre_map{$key} = chr(hex($unicode_map{$key})) unless (t2h_encoding_is_entity($pre_map{$key}));
      }
    }
    @t2h_enable_encoding_accents_stack = ();
  }
}

sub t2h_default_string_width($)
{
   my $string = shift;
   if (get_conf('USE_UNICODE'))
   {
       my $width = 0;
       foreach my $character(split '', $string)
       {
          if ($character =~ /\p{Unicode::EastAsianWidth::InFullwidth}/)
          {
             $width += 2;
          }
          else 
          {
             $width += 1;
          }
       }
       return $width;
   }
   else
   {
       return length($string);
   }
}

sub t2h_default_finish_out()
{
}


########################################################################
# Control of Page layout:
# You can make changes of the Page layout at two levels:
# 1.) For small changes, it is often enough to change the value of
#     some global string/hash/array variables
# 2.) For larger changes, reimplement one of the T2H_DEFAULT_<fnc>* routines,
#     give them another name, and assign them to the respective
#     $<fnc> variable.

# As a general interface, the hashes Texi2HTML::HREF, Texi2HTML::NAME, Texi2HTML::NODE, Texi2HTML::NO_TEXI, Texi2HTML::SIMPLE_TEXT hold
# href, html-name, node-name, name after removal of texi commands of
# This     -- current section (resp. html page)
# Top      -- top element
# Contents -- Table of contents element
# Overview -- Short table of contents element
# Index    -- Index page element
# About    -- page which explain "navigation buttons" element
# First    -- first node element
# Last     -- last node element
#
# Whether or not the following hash values are set, depends on the context
# (all values are w.r.t. 'This' section)
# Next        -- next element of texinfo
# Prev        -- previous element of texinfo
# NodeUp      -- up node of texinfo
# NodeForward -- next node in node reading order, taking menu into account
# NodeBack    -- previous node in node reading order, taking menu into account
# Forward     -- next node in reading order
# Back        -- previous node in reading order
# Up          -- parent given by sectioning commands
# FastForward -- if leave node, up and next, else next node
# FastBack    -- if leave node, up and prev, else prev node
#
# Furthermore, the following global variabels are set:
# $Texi2HTML::THISDOC{'title'}          -- title as set by @title...
# $Texi2HTML::THISDOC{'title_no_texi'}  -- title without texi (without html elements)
# $Texi2HTML::THISDOC{'title_texi'}     -- title with texinfo @-commands
# $Texi2HTML::THISDOC{'fulltitle'}      -- full title as set by @title...
# $Texi2HTML::THISDOC{'subtitle'}       -- subtitle as set by @subtitle
# $Texi2HTML::THISDOC{'author'}         -- author as set by @author
# $Texi2HTML::THISDOC{'copying_comment'}  -- text of @copying and @end copying in comment
#
# $Texi2HTML::THISDOC{'program'}          -- name of program generating the output
# $Texi2HTML::THISDOC{'program_homepage'} -- homepage of program
# $Texi2HTML::THISDOC{'toc_file}         -- table of contents file
# $Texi2HTML::THISDOC{'file_base_name'}   -- base name of the texinfo manual file
# $Texi2HTML::THISDOC{'input_file_name'}  -- name of the texinfo manual file
# $Texi2HTML::THISDOC{'destination_directory'}
                                 #      -- directory for the resulting files
# $Texi2HTML::THISDOC{'css_import_lines'} -- ref on @import lines in css files
# $Texi2HTML::THISDOC{'css_rule_lines'}   -- ref on css rules lines
#
# and pointer to arrays of lines which need to be printed by main::print_lines
# $Texi2HTML::THIS_SECTION  -- lines of 'This' section
# $Texi2HTML::OVERVIEW      -- lines of short table of contents
# $Texi2HTML::TOC_LINES     -- lines of table of contents
# $Texi2HTML::TITLEPAGE     -- lines of title page
#
# $Texi2HTML::THIS_ELEMENT  holds the element reference.  

# most of the functions are either reset when switching format, in 
# t2h_default_set_variables_default, or set in format, the simplest
# one being setup above in t2h_default_raw_text_load

#
# The following generic subs control the layout:
#
# misc element formatting functions. They are rather generic, 
# their call is controlled by other variables (separate or not
# footnotes, about_body, handling of table of contents...).
# print_Footnotes is the only to be redefined, in info
$print_Toc		      = \&T2H_DEFAULT_print_Toc;
$print_Overview	      = \&T2H_DEFAULT_print_Overview;
$print_About	      = \&T2H_DEFAULT_print_About;
$print_misc		      = \&T2H_DEFAULT_print_misc;
# generic enough (call print_page_head if needed)
$print_Top_header         = \&T2H_DEFAULT_print_Top_header;

# the following are less generic, but in case a specific format
# doesn't redefine them, the raw text functions are always defined.
$print_page_head              = \&T2H_DEFAULT_print_page_head;
$contents                 = \&T2H_DEFAULT_contents;
$shortcontents            = \&T2H_DEFAULT_shortcontents;
$one_section              = \&T2H_DEFAULT_one_section;
$print_Top                = \&T2H_DEFAULT_print_Top;
$print_Top_footer             = \&T2H_DEFAULT_print_Top_footer;
$print_misc_header            = \&T2H_DEFAULT_print_misc_header;
$print_misc_footer            = \&T2H_DEFAULT_print_misc_footer;
$print_section_footer     = \&T2H_DEFAULT_print_section_footer;
$print_chapter_header     = \&T2H_DEFAULT_print_chapter_header;
$print_section_header     = \&T2H_DEFAULT_print_section_header;
$print_chapter_footer     = \&T2H_DEFAULT_print_chapter_footer;
$print_page_foot              = \&T2H_DEFAULT_print_page_foot;
$print_head_navigation    = \&T2H_DEFAULT_print_head_navigation;
$print_foot_navigation    = \&T2H_DEFAULT_print_foot_navigation;
$end_section              = \&T2H_DEFAULT_end_section;
# changed in info
$print_Footnotes              = \&T2H_DEFAULT_print_Footnotes;
# used if split
$about_body                 = \&T2H_DEFAULT_about_body;
$print_navigation           = \&T2H_DEFAULT_print_navigation;

#
# generic formatting functions
#

$button_icon_img	      = \&T2H_DEFAULT_button_icon_img;
# not really needed nor relevant except for html
$print_frame              = \&T2H_DEFAULT_print_frame;
$print_toc_frame          = \&T2H_DEFAULT_print_toc_frame;
# generic
$titlepage                 = \&T2H_DEFAULT_titlepage;
$css_lines                 = \&T2H_DEFAULT_css_lines;
$print_redirection_page    = \&T2H_DEFAULT_print_redirection_page;
$node_file_name            = \&T2H_DEFAULT_node_file_name;
$inline_contents           = \&T2H_DEFAULT_inline_contents;
$program_string            = \&T2H_DEFAULT_program_string;
$element_file_name         = \&t2h_default_element_file_name;
 
########################################################################
# Layout for every sections
#

sub T2H_DEFAULT_print_section($$$$)
{
    my $fh = shift;
    my $first_in_page = shift;
    my $previous_is_top = shift;
    my $element = shift;

    my $nw = main::print_lines($fh);
}

sub T2H_DEFAULT_one_section($$)
{
    my $fh = shift;
    my $element = shift;
    main::print_lines($fh);
    &$print_page_foot($fh);
}

###################################################################
# Layout of top-page. It is possible to use @ifnothtml, @ifhtml,
# @html within the Top texinfo node to specify content of top-level
# page.
#
sub T2H_DEFAULT_print_Top_header($$)
{
    my $fh = shift;
    my $do_page_head = shift;
    &$print_page_head($fh) if ($do_page_head);
}
sub T2H_DEFAULT_print_Top_footer($$$)
{
    my $fh = shift;
    my $end_page = shift;
    my $element = shift;
    if ($end_page)
    {
        &$print_page_foot($fh);
    }
}

sub T2H_DEFAULT_print_Top($$$)
{
    my $fh = shift;
    my $has_top_heading = shift;
    my $element = shift;

    if (get_conf('setshortcontentsaftertitlepage'))
    {
        my $shortcontents = &$inline_contents($fh, 'shortcontents');
        print $fh "".join('',@$shortcontents) if (defined($shortcontents));
    }
    if (get_conf('setcontentsaftertitlepage'))
    {
        my $contents = &$inline_contents($fh, 'contents');
        print $fh "".join('',@$contents) if (defined($contents));
    }

    main::print_lines($fh, $Texi2HTML::THIS_SECTION);
}

###################################################################
# Layout of Toc, Overview, and Footnotes pages
# By default, we use "normal" layout
# Texi2HTML::HREF of Next, Prev, Up, Forward, Back, etc are not defined
# redefine \@MISC_BUTTONS to change the navigation
sub T2H_DEFAULT_print_Toc
{
    return &$print_misc(@_);
}
sub T2H_DEFAULT_print_Overview
{
    return &$print_misc(@_);
}
sub T2H_DEFAULT_print_Footnotes
{
    return &$print_misc(@_);
}
sub T2H_DEFAULT_print_About
{
    return &$print_misc(@_);
}

sub T2H_DEFAULT_print_misc_header($$$$)
{
    my $fh = shift;
    my $buttons = shift;
    my $new_file = shift;
    my $misc_page = shift;
    &$print_page_head($fh) if ($new_file);
}

sub T2H_DEFAULT_print_misc_footer($$$)
{
    my $fh = shift;
    my $buttons = shift;
    my $new_file = shift;
    if ($new_file)
    {
        &$print_page_foot($fh);
    }
}

use vars qw(
%t2h_default_underline_symbol
);

%t2h_default_underline_symbol = (
  0 => '*',
  1 => '*',
  2 => '=',
  3 => '-',
  4 => '.'
);

sub t2h_default_heading_text($$$)
{
    my $command = shift;
    my $text = shift;
    my $level = shift;

    return '' if ($text !~ /\S/);
    my $result = $text ."\n";
    # as seen in encodings/nodetest_utf8_no_unicode, the length can be in
    # bytes (certainly) when there hasn't been a require Encode
    #$result .=($t2h_default_underline_symbol{$level} x length($text))."\n";
    $result .=($t2h_default_underline_symbol{$level} x t2h_default_string_width($text))."\n";
    return $result;
}

sub t2h_default_heading_text_preformatted($$$)
{
    my $command = shift;
    my $text = shift;
    my $level = shift;

    return t2h_default_heading_text($command, $text, $level);
}

sub T2H_DEFAULT_print_misc($$$)
{
    my $fh = shift;
    my $new_file = shift;
    my $misc_page = shift;
    my $buttons = \@MISC_BUTTONS;
    &$print_misc_header($fh, $buttons, $new_file, $misc_page);
    print $fh "".&$heading_text('misc heading', $Texi2HTML::NAME{This}, 1) . "\n";
    main::print_lines($fh);
    &$print_misc_footer($fh, $buttons, $new_file);
}
##################################################################
# section_footer is only called if SPLIT eq 'section'
# section_footer: after print_section of last section, before print_page_foot
#

sub T2H_DEFAULT_print_section_footer
{
    my $fh = shift;
    my $element = shift;
}

###################################################################
# chapter_header and chapter_footer are only called if
# SPLIT eq 'chapter'
# chapter_header: after print_page_head, before print_section
# chapter_footer: after print_section of last section, before print_page_foot

sub T2H_DEFAULT_print_chapter_header($$)
{
    my $fh = shift;
    my $element = shift;
}

sub T2H_DEFAULT_print_chapter_footer($$)
{
    my $fh = shift;
    my $element = shift;
}

sub T2H_DEFAULT_print_section_header($$)
{
    my $fh = shift;
    my $element = shift;
}


###################################################################
# Layout of standard header and footer
#

sub T2H_DEFAULT_print_page_head($)
{
    my $fh = shift;
}

sub T2H_DEFAULT_program_string()
{
    my $date = get_conf('today');
    $date = '' if (!defined($date));
    if ($date ne '')
    {
        return gdt('This document was generated on @emph{{date}} using @uref{{program_homepage}, @emph{{program}}}.', {
           'date' => $date, 'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program' => $Texi2HTML::THISDOC{'program_and_version'} },{'duplicate'=>1});
    }
    return gdt('This document was generated using @uref{{program_homepage}, @emph{{program}}}.', {
       'program_homepage' => $Texi2HTML::THISDOC{'program_homepage'}, 'program'
=> $Texi2HTML::THISDOC{'program_and_version'} },{'duplicate'=>1});
}

sub T2H_DEFAULT_end_section($$$)
{
    my $fh = shift;
    my $misc_or_top_and_section_separation = shift;
    my $element = shift;
}

sub T2H_DEFAULT_print_page_foot($)
{
    my $fh = shift;
}

###################################################################
# Layout of navigation panel

sub T2H_DEFAULT_print_head_navigation($$$$$)
{
    my $fh = shift;
    my $buttons = shift;
    my $first_in_page = shift;
    my $previous_is_top = shift;
    my $element = shift;

    return '';
}

sub T2H_DEFAULT_print_foot_navigation($$$$$;$)
{
    my $fh = shift;
    my $buttons = shift;
    my $rule = shift;
    my $print_navigation_panel = shift;
    my $element = shift;
    my $maybe_in_page = shift;

    $rule = '' if (!defined($rule));
    print $fh "$rule\n" if ($rule ne '');
}

######################################################################
# navigation panel
#
# how to create IMG tag
# this is only used in html, and only if ICONS is set and the button
# is active.
sub T2H_DEFAULT_button_icon_img
{
    my $button = shift;
    my $icon = shift;
    my $name = shift;
    return '' if (!defined($icon));
    $button = "" if (!defined ($button));
    $name = '' if (!defined($name));
    my $alt = ''; 
    if ($name ne '')
    {
        if ($button ne '')
        {
            $alt = "$button: $name";
        }
        else
        {
            $alt = $name;
        }  
    }
    else
    {
        $alt = $button;
    }
    return "$icon $alt";
}

sub T2H_DEFAULT_print_navigation
{
    my $buttons = shift;
    my $vertical = shift;

    return '';
}

######################################################################
# Frames: this is from "Richard Y. Kim" <ryk@coho.net>
# Should be improved to be more conforming to other _print* functions
# toc_file and main_file passed as args are relative to the texinfo manual
# location, and therefore are not used.

# no-ops in the default case, doesn't really make sense if output is 
# not html

sub T2H_DEFAULT_print_frame
{
    my $fh = shift;
    my $toc_file = shift;
    my $main_file = shift;
    $main_file = $Texi2HTML::THISDOC{'filename'}->{'top'};
    $toc_file = $Texi2HTML::THISDOC{'filename'}->{'toc_frame'};
}

sub T2H_DEFAULT_print_toc_frame
{
    my $fh = shift;
    my $stoc_lines = shift;
}

# This subroutine is intended to fill @Texi2HTML::TOC_LINES and 
# @Texi2HTML::OVERVIEW with the table of contents and short table of
# contents.
#
# arguments:
# ref on an array containing all the elements

# each element is a reference on a hash. The following keys might be of
# use:
# 'top': true if this is the top element
# 'toc_level': level of the element in the table of content. Highest level
#              is 1 for the @top element and for chapters, appendix and so on,
#              2 for section, unnumberedsec and so on... 
# 'tocid': label used for reference linking to the element in table of
#          contents
# 'file': the file containing the element, usefull to do href to that file
#         in case the document is split.
# 'text': text of the element, with section number
# 'text_nonumber': text of the element, without section number

# Relevant configuration variables are:
# $NO_BULLET_LIST_ATTRIBUTE: usefull in case a list is used
# $FRAMES: @Texi2HTML::OVERVIEW is used in one of the frames. 
# $BEFORE_OVERVIEW
# $AFTER_OVERVIEW
# $BEFORE_TOC_LINES
# $AFTER_TOC_LINES
# get_conf('contents')
# get_conf('shortcontents')

sub T2H_DEFAULT_contents($$)
{
   my $elements = shift;
   my $toc_file = shift;
   my @result;
   return unless (get_conf('contents'));
   foreach my $element (@$elements)
   {
      my $level = $element->{'toc_level'};
      $level = 1 if ($level < 1);
      my $text =  $element->{'text'};
      my $result =  (' ' x ($level - 1)) . $text ."\n";
      push @result, $result;
   }
   if (@result)
   {
      unshift @result, $BEFORE_TOC_LINES;
      push @result, $AFTER_TOC_LINES;
   }
   return \@result;
}

sub T2H_DEFAULT_shortcontents($$)
{
   my $elements = shift;
   my $stoc_file = shift;
   my @result;
   return unless (get_conf('shortcontents'));
   foreach my $element (@$elements)
   {
      my $level = $element->{'toc_level'};
      next if ($level > 1);
      $level = 1 if ($level < 1);
      my $text = $element->{'text'};
      push @result, $text ."\n";
   }
   if (@result)
   {
      unshift @result, $BEFORE_OVERVIEW;
      push @result, $AFTER_OVERVIEW;
   }
   return \@result;
}

sub T2H_DEFAULT_print_title()
{
    my $element = shift;
    return undef unless (get_conf('SHOW_TITLE'));
    if (get_conf('USE_TITLEPAGE_FOR_TITLE'))
    {
        my ($titlepage_text, $titlepage_no_texi, $titlepage_simple_format) = main::do_special_region_lines('titlepage',$Texi2HTML::THISDOC{'state'});

        &$titlepage([],$titlepage_text, $titlepage_no_texi, $titlepage_simple_format);
        return $Texi2HTML::TITLEPAGE;
    }
    else
    {
       my $title = '';
       $title = $Texi2HTML::THISDOC{'simpletitle'} if (defined($Texi2HTML::THISDOC{'simpletitle'}) and $Texi2HTML::THISDOC{'simpletitle'} !~ /^\s*$/);
       if ($title ne '')
       {
           return &$heading_text('@settitle', $title, 0) . "\n";
       }
    }
}

sub T2H_DEFAULT_toc_body($)
{
    my $elements_list = shift;
    my $toc_lines = &$contents($elements_list, $Texi2HTML::THISDOC{'toc_file'});
    @{$Texi2HTML::TOC_LINES} = @$toc_lines if ($toc_lines);
    my $stoc_lines = &$shortcontents($elements_list, $Texi2HTML::THISDOC{'stoc_file'});
    @{$Texi2HTML::OVERVIEW} = @$stoc_lines if ($stoc_lines);
}

# element and elements_list may not be undef when called from the 
# main program, but may be if called from other customization function,
# for example, here, print_Top.
sub T2H_DEFAULT_inline_contents($$$$)
{
    my $fh = shift;
    my $command = shift;
    my $element = shift;
    my $elements_list = shift;
    my $name;
    my $lines;

    my $toc_file;
    $toc_file = $element->{'file'} if (defined($element));

    my $result = undef;

    if ($command eq 'contents')
    {
        $name = $Texi2HTML::NAME{'Contents'};
        $toc_file = $Texi2HTML::THISDOC{'toc_file'} if (!defined($toc_file));
        if (defined($elements_list))
        {
            $lines = &$contents($elements_list, $toc_file);
        }
        else
        {
            $lines = $Texi2HTML::TOC_LINES;
        }
    }
    else
    {
        $name = $Texi2HTML::NAME{'Overview'};
        $toc_file = $Texi2HTML::THISDOC{'stoc_file'} if (!defined($toc_file));
        if (defined($elements_list))
        {
            $lines = &$shortcontents($elements_list, $toc_file);
        }
        else
        {
            $lines = $Texi2HTML::OVERVIEW;
        }
    }
    if ($lines and @{$lines})
    {
         $result = [ &$heading_text("\@$command", $name, 1), "\n" ];
         my $contents_anchor = &$anchor($element->{'id'});
         if (defined($contents_anchor) and $contents_anchor =~ /\S/)
         {
             unshift @$result, $contents_anchor."\n";
         }
         push @$result, (@$lines, "\n");
    }
    return $result;
}


sub T2H_DEFAULT_css_lines ($$)
{
    my $import_lines = shift;
    my $rule_lines = shift;
    return if ((!@$rule_lines and !@$import_lines and !keys(%css_map) and !@CSS_REFS) or get_conf('NO_CSS'));
    my $css_text = "<style type=\"text/css\">\n<!--\n";
    $css_text .= join('',@$import_lines) . "\n" if (@$import_lines);
    foreach my $css_rule (sort(keys(%css_map)))
    {
        next unless ($css_map{$css_rule});
        $css_text .= "$css_rule {$css_map{$css_rule}}\n";
    }
    $css_text .= join('',@$rule_lines) . "\n" if (@$rule_lines);
    $css_text .= "-->\n</style>\n";
    foreach my $ref (@CSS_REFS)
    {
        $css_text .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$ref\">\n";
    }
    set_from_document('CSS_LINES', $css_text);
}

######################################################################
# About page
#

# PRE_ABOUT can be a function reference or a scalar.
# Note that if it is a scalar, T2H_InitGlobals has not been called,
# and all global variables like $ADDRESS are not available.
$PRE_ABOUT = sub
{
    return '  ' . &$program_string() .  "\n";
};

# If customizing $AFTER_ABOUT, be sure to put the content inside <p></p>.
$AFTER_ABOUT = '';

%BUTTONS_EXAMPLE =
    (
     'Top',         ' ',
     'Contents',    ' ',
     'Overview',    ' ',
     'Index',       ' ',
     'This',        '1.2.3',
     'Back',        '1.2.2',
     'FastBack',    '1',
     'Prev',        '1.2.2',
     'Up',          '1.2',
     'Next',        '1.2.4',
     'NodeUp',      '1.2',
     'NodeNext',    '1.2.4',
     'NodePrev',    '1.2.2',
     'NodeForward', '1.2.4',
     'NodeBack',    '1.2.2',
     'Forward',     '1.2.4',
     'FastForward', '2',
     'About',       ' ',
     'First',       '1.',
     'Last',        '1.2.4',
     'NextFile',    ' ',
     'PrevFile',    ' ',
    );

sub T2H_DEFAULT_about_body
{
    my $about = "";
    if (ref($PRE_ABOUT) eq 'CODE')
    {
        $about .= &$PRE_ABOUT();
    }
    else
    {
        $about .= $PRE_ABOUT;
    }
    return $about;
}

# return value is currently ignored
sub T2H_DEFAULT_titlepage($$$$)
{
    my $titlepage_lines = shift;
    my $titlepage_text = shift;
    my $titlepage_no_texi = shift;
    my $titlepage_simple_format = shift;

    $Texi2HTML::TITLEPAGE = $titlepage_text;
    if ($titlepage_text eq '')
    {
       my $title = '';
       $title = $Texi2HTML::THISDOC{'simpletitle'} if (defined($Texi2HTML::THISDOC{'simpletitle'}) and $Texi2HTML::THISDOC{'simpletitle'} !~ /^\s*$/);
       if ($title ne '')
       {
           $Texi2HTML::TITLEPAGE = &$heading_text('@settitle', $title, 0);
           $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
       }
    }
    else
    {
        $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
    }

    if (get_conf('setcontentsaftertitlepage') and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'contents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
    {
        foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'contents'}})
        {
            $Texi2HTML::TITLEPAGE .= $line;
        }
        $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
    }
    if (get_conf('setshortcontentsaftertitlepage') and (defined($Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'})) and @{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
    {
        foreach my $line(@{$Texi2HTML::THISDOC{'inline_contents'}->{'shortcontents'}})
        {
            $Texi2HTML::TITLEPAGE .= $line;
        }
        $Texi2HTML::TITLEPAGE .= "$DEFAULT_RULE\n";
    }
    return $Texi2HTML::TITLEPAGE;
}


sub T2H_DEFAULT_print_redirection_page()
{
    #return "Redirection files are not of use for the current format.\n";
    return undef;
}

sub T2H_DEFAULT_node_file_name($$)
{
    my $node = shift;
    my $type = shift;
    return undef if ($node->{'external_node'}
       or ($type eq 'top' and !get_conf('NEW_CROSSREF_STYLE')));
    my $node_file_base;
    if ($type eq 'top' and defined(get_conf('TOP_NODE_FILE')))
    {
        $node_file_base = get_conf('TOP_NODE_FILE');
    }
    elsif (get_conf('NEW_CROSSREF_STYLE'))
    {
        if (get_conf('TRANSLITERATE_FILE_NAMES'))
        {
            $node_file_base = $node->{'cross_manual_file'};
        }
        else
        {
            $node_file_base = $node->{'cross_manual_target'};
        }
    }
    else
    {
         $node_file_base = main::remove_texi($node->{'texi'});
         $node_file_base =~ s/[^\w\.\-]/-/g;
    }
    if (defined(get_conf('NODE_FILE_EXTENSION')) and get_conf('NODE_FILE_EXTENSION') ne '')
    {
        return ($node_file_base . '.' . get_conf('NODE_FILE_EXTENSION'));
    }
    return $node_file_base;
}

########################################################################
# Control of formatting:
# 1.) For some changes, it is often enough to change the value of
#     some global map. It might necessitate building a little
#     function along with the change in hash, if the change is the use
#     of another function (in style_map).
# 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines,
#     give them another name, and assign them to the respective
#     $<fnc> variable (below).

%deprecated_commands = (
  'ctrl' => '',
  'allow-recursion' => N__('recursion is always allowed'),
  'quote-arg' => N__('arguments are quoted by default'),
);

#
# This hash should have keys corresponding with the nonletter command accent
# whose following character is considered to be the argument
# This hash associates an accent macro to the ISO name for the accent if any.
# The customary use of this map is to find the ISO name appearing in html
# entity (like &eacute;) associated with a texinfo accent macro.
#
# The keys of the hash are
# ": umlaut
# ~: tilda accent
# ^: circumflex accent
# `: grave accent
# ': acute accent
# =: macron accent
%accent_map = (
          '"',  'uml',
          '~',  'tilde',
          '^',  'circ',
          '`',  'grave',
          "'", 'acute',
          ",", 'cedil',
          '=', '',
          'ringaccent', 'ring',
          'H', '',
          'dotaccent', '',
          'u', '',
          'ubaraccent', '',
          'udotaccent', '',
          'v', '',
          'ogonek', 'ogon',
         );

#
# ascii representation of texinfo "simple things" @-commands
%default_simple_map = (
           '*', "\n",
           ' ', ' ',
           "\t", ' ',
           "\n", ' ',
           '-', '',  # hyphenation hint
           '|', '',  # used in formatting commands @evenfooting and friends
           '/', '',
           ':', '',
           '!', '!',
           '?', '?',
           '.', '.',
           '@', '@',
           '}', '}',
           '{', '{',
);

# texinfo "simple things" @-commands
%simple_map = %default_simple_map;

# this map is used in preformatted text
%simple_map_pre = %simple_map;

# This map is used when texi elements are removed and replaced 
# by simple text
%simple_map_texi = %default_simple_map;

# maps for the math specific commands
%simple_map_math = (
           '\\', '\\'
           );

#%simple_map_pre_math = %simple_map_math;
#%simple_map_texi_math = %simple_map_math;

$punctuation_characters = '.?!';
$after_punctuation_characters = '"\')]';


%default_things_map = (
               'TeX'          => 'TeX',
               'LaTeX'          => 'LaTeX',
               'bullet'       => '*',
               'copyright' => '(C)',
               'registeredsymbol'   => '(R)',
               'dots'         => '...',
               'enddots'      => '...',
               'equiv'        => '==',
# FIXME i18n
               'error'        => 'error-->',
               'expansion'    => '==>',
               'arrow'        => '->',
               'minus'        => '-',
               'point'        => '-!-',
               'print'        => '-|',
               'result'       => '=>',
               'today'        => '',
               'aa'           => 'aa',
               'AA'           => 'AA',
               'ae'           => 'ae',
               'oe'           => 'oe', 
               'AE'           => 'AE',
               'OE'           => 'OE',
               'o'            => '/o',
               'O'            => '/O',
               'ss'           => 'ss',
               'l'            => '/l',
               'L'            => '/L',
               'DH'           => 'D',
               'dh'           => 'd',
               'TH'           => 'TH', # http://www.evertype.com/standards/wynnyogh/thorn.html

               'th'           => 'th',
               'exclamdown'   => '!',
               'questiondown' => '?',
               'pounds'       => '#',
               'ordf'         => 'a',
               'ordm'         => 'o',
               'comma'        => ',',
               'euro'         => 'Euro',
               'geq'          => '>=',
               'leq'          => '<=',
               'tie'          => ' ',
               'textdegree'          => 'o',
               'quotedblleft'          => '``',
               'quotedblright'          => "''",
               'quoteleft'          => '`',
               'quoteright'          => "'",
               'quotedblbase'          => ',,',
               'quotesinglbase'          => ',',
               'guillemetleft'          => '<<',
               'guillemetright'          => '>>',
               'guillemotleft'          => '<<',
               'guillemotright'          => '>>',
               'guilsinglleft'          => '<',
               'guilsinglright'          => '>',
);

%things_map = %default_things_map;

# This map is used in preformatted environments
%pre_map = %things_map;

# used in math. If not found, pre_map is used.
%math_map = ();

# text replacing macros when texi commands are removed and plain text is 
# produced.
%texi_map = %default_things_map;

# used for index sorting.
%sorting_things_map = %default_things_map;
foreach my $accent_letter ('o','O','l','L')
{
  $sorting_things_map{$accent_letter} = $accent_letter;
}
$sorting_things_map{'copyright'} = 'C';
$sorting_things_map{'registeredsymbol'} = 'R';
$sorting_things_map{'today'} = 't';

%default_texi_map = %texi_map;

#
# texinfo "things" (@foo{}) to XML ones
#
%things_map_xml = (
               'TeX'          => 'TeX',
               'LaTeX'          => 'LaTeX',
# pertusus: unknown by makeinfo, not in texinfo manual (@* is the right thing)
#               'br', '<br>',     # paragraph break
               'bullet'       => '&bull;',
#               #'copyright' => '(C)',
               'copyright'    => '&copy;',
               'registeredsymbol'   => '&reg;',
               'dots'         => '&hellip;',
               'enddots'      => '...',
               'equiv'        => '&equiv;',
# FIXME i18n
               'error'        => 'error--&gt;',
               'expansion'    => '&rarr;',
               'arrow'        => '&rarr;',
               'minus'        => '-',
               'point'        => '&lowast;',
               'print'        => '-|',
               'result'       => '&rArr;',
               # set in code using the language
               # 'today', &pretty_date,
               'today'        => '',
               'aa'           => '&aring;',
               'AA'           => '&Aring;',
               'ae'           => '&aelig;',
               'oe'           => '&oelig;', #pertusus: also &#156;. &oelig; not in html 3.2
               'AE'           => '&AElig;',
               'OE'           => '&OElig;', #pertusus: also &#140;. &OElig; not in html 3.2
               'o'            =>  '&oslash;',
               'O'            =>  '&Oslash;',
               'ss'           => '&szlig;',
               'DH'           => '&ETH;',
               'dh'           => '&eth;',
               'TH'           => '&THORN;',
               'th'           => '&thorn;',
               'l'            => '&#322;',
               'L'            => '&#321;',
               'exclamdown'   => '&iexcl;',
               'questiondown' => '&iquest;',
               'pounds'       => '&pound;',
               'ordf'         => '&ordf;',
               'ordm'         => '&ordm;',
               'comma'        => ',',
               'euro'         => '&euro;',
               'geq'          => '&ge;',
               'leq'          => '&le;',
               'tie'          => '&nbsp;',
               'textdegree'          => '&deg;',
               'quotedblleft'          => '&ldquo;',
               'quotedblright'          => '&rdquo;',
               'quoteleft'          => '&lsquo;',
               'quoteright'          => '&rsquo;',
               'quotedblbase'          => '&bdquo;',
               'quotesinglbase'          => '&sbquo;',
               'guillemetleft'          => '&laquo;',
               'guillemetright'          => '&raquo;',
               'guillemotleft'          => '&laquo;',
               'guillemotright'          => '&raquo;',
               'guilsinglleft'          => '&lsaquo;',
               'guilsinglright'          => '&rsaquo;',
             );

# This map is used in preformatted environments
%pre_map_xml = %things_map_xml;

# taken from
#Latin extended additionnal
#http://www.alanwood.net/unicode/latin_extended_additional.html
#C1 Controls and Latin-1 Supplement
#http://www.alanwood.net/unicode/latin_1_supplement.html
#Latin Extended-A
#http://www.alanwood.net/unicode/latin_extended_a.html
#Latin Extended-B
#http://www.alanwood.net/unicode/latin_extended_b.html
#dotless i: 0131

#http://www.alanwood.net/unicode/arrows.html 21**
#http://www.alanwood.net/unicode/general_punctuation.html 20**
#http://www.alanwood.net/unicode/mathematical_operators.html 22**

%unicode_map = (
               'bullet'       => '2022',
               'copyright'    => '00A9',
               'registeredsymbol'   => '00AE',
               'dots'         => '2026',
               'enddots'      => '',
               'equiv'        => '2261',
               'error'        => '',
               'expansion'    => '2192',
               'arrow'        => '2192',
               'minus'        => '2212', # in mathematical operators
#               'minus'        => '002D', # in latin1
               'point'        => '2605',
               'print'        => '22A3',
               'result'       => '21D2',
               'today'        => '',
               'aa'           => '00E5',
               'AA'           => '00C5',
               'ae'           => '00E6',
               'oe'           => '0153',
               'AE'           => '00C6',
               'OE'           => '0152',
               'o'            => '00F8',
               'O'            => '00D8',
               'ss'           => '00DF',
               'DH'           => '00D0',
               'dh'           => '00F0',
               'TH'           => '00DE',
               'th'           => '00FE',
               'l'            => '0142',
               'L'            => '0141',
               'exclamdown'   => '00A1',
               'questiondown' => '00BF',
               'pounds'       => '00A3',
               'ordf'         => '00AA',
               'ordm'         => '00BA',
               'comma'        => '002C',
               'euro'         => '20AC',
               'geq'          => '2265',
               'leq'          => '2264',
               'tie'          => '',
#               'tie'          => '0020',
               'textdegree'          => '00B0',
               'quotedblleft'          => '201C',
               'quotedblright'          => '201D',
               'quoteleft'          => '2018',
               'quoteright'          => '2019',
               'quotedblbase'          => '201E',
               'quotesinglbase'          => '201A',
               'guillemetleft'          => '00AB',
               'guillemetright'          => '00BB',
               'guillemotleft'          => '00AB',
               'guillemotright'          => '00BB',
               'guilsinglleft'          => '2039',
               'guilsinglright'          => '203A',
             );

%makeinfo_encoding_to_map = (
  "iso-8859-1",  'iso8859_1',
  "iso-8859-2",  'iso8859_2',
  "iso-8859-15", 'iso8859_15',
  "koi8-r",      'koi8',
  "koi8-u",      'koi8', 
);

foreach my $encoding (keys(%makeinfo_encoding_to_map))
{
   $t2h_encoding_aliases{$encoding} = $encoding;
   $t2h_encoding_aliases{$makeinfo_encoding_to_map{$encoding}} = $encoding;
}

# cut and pasted from eigth_bit_makeinfo_maps.pl, in turn generated with
# ./parse_8bit_makeinfo_maps.pl

%makeinfo_unicode_to_eight_bit = (
   'iso8859_1' => {
      '00A0' => 'A0',
      '00A1' => 'A1',
      '00A2' => 'A2',
      '00A3' => 'A3',
      '00A4' => 'A4',
      '00A5' => 'A5',
      '00A6' => 'A6',
      '00A7' => 'A7',
      '00A8' => 'A8',
      '00A9' => 'A9',
      '00AA' => 'AA',
      '00AB' => 'AB',
      '00AC' => 'AC',
      '00AD' => 'AD',
      '00AE' => 'AE',
      '00AF' => 'AF',
      '00B0' => 'B0',
      '00B1' => 'B1',
      '00B2' => 'B2',
      '00B3' => 'B3',
      '00B4' => 'B4',
      '00B5' => 'B5',
      '00B6' => 'B6',
      '00B7' => 'B7',
      '00B8' => 'B8',
      '00B9' => 'B9',
      '00BA' => 'BA',
      '00BB' => 'BB',
      '00BC' => 'BC',
      '00BD' => 'BD',
      '00BE' => 'BE',
      '00BF' => 'BF',
      '00C0' => 'C0',
      '00C1' => 'C1',
      '00C2' => 'C2',
      '00C3' => 'C3',
      '00C4' => 'C4',
      '00C5' => 'C5',
      '00C6' => 'C6',
      '00C7' => 'C7',
      '00C7' => 'C7',
      '00C8' => 'C8',
      '00C9' => 'C9',
      '00CA' => 'CA',
      '00CB' => 'CB',
      '00CC' => 'CC',
      '00CD' => 'CD',
      '00CE' => 'CE',
      '00CF' => 'CF',
      '00D0' => 'D0',
      '00D1' => 'D1',
      '00D2' => 'D2',
      '00D3' => 'D3',
      '00D4' => 'D4',
      '00D5' => 'D5',
      '00D6' => 'D6',
      '00D7' => 'D7',
      '00D8' => 'D8',
      '00D9' => 'D9',
      '00DA' => 'DA',
      '00DB' => 'DB',
      '00DC' => 'DC',
      '00DD' => 'DD',
      '00DE' => 'DE',
      '00DF' => 'DF',
      '00E0' => 'E0',
      '00E1' => 'E1',
      '00E2' => 'E2',
      '00E3' => 'E3',
      '00E4' => 'E4',
      '00E5' => 'E5',
      '00E6' => 'E6',
      '00E7' => 'E7',
      '00E8' => 'E8',
      '00E9' => 'E9',
      '00EA' => 'EA',
      '00EB' => 'EB',
      '00EC' => 'EC',
      '00ED' => 'ED',
      '00EE' => 'EE',
      '00EF' => 'EF',
      '00F0' => 'F0',
      '00F1' => 'F1',
      '00F2' => 'F2',
      '00F3' => 'F3',
      '00F4' => 'F4',
      '00F5' => 'F5',
      '00F6' => 'F6',
      '00F7' => 'F7',
      '00F8' => 'F8',
      '00F9' => 'F9',
      '00FA' => 'FA',
      '00FB' => 'FB',
      '00FC' => 'FC',
      '00FD' => 'FD',
      '00FE' => 'FE',
      '00FF' => 'FF',
   },
   'iso8859_15' => {
      '00A0' => 'A0',
      '00A1' => 'A1',
      '00A2' => 'A2',
      '00A3' => 'A3',
      '20AC' => 'A4',
      '00A5' => 'A5',
      '0160' => 'A6',
      '00A7' => 'A7',
      '0161' => 'A8',
      '00A9' => 'A9',
      '00AA' => 'AA',
      '00AB' => 'AB',
      '00AC' => 'AC',
      '00AD' => 'AD',
      '00AE' => 'AE',
      '00AF' => 'AF',
      '00B0' => 'B0',
      '00B1' => 'B1',
      '00B2' => 'B2',
      '00B3' => 'B3',
      '017D' => 'B4',
      '00B5' => 'B5',
      '00B6' => 'B6',
      '00B7' => 'B7',
      '017E' => 'B8',
      '00B9' => 'B9',
      '00BA' => 'BA',
      '00BB' => 'BB',
      '0152' => 'BC',
      '0153' => 'BD',
      '0178' => 'BE',
      '00BF' => 'BF',
      '00C0' => 'C0',
      '00C1' => 'C1',
      '00C2' => 'C2',
      '00C3' => 'C3',
      '00C4' => 'C4',
      '00C5' => 'C5',
      '00C6' => 'C6',
      '00C7' => 'C7',
      '00C8' => 'C8',
      '00C9' => 'C9',
      '00CA' => 'CA',
      '00CB' => 'CB',
      '00CC' => 'CC',
      '00CD' => 'CD',
      '00CE' => 'CE',
      '00CF' => 'CF',
      '00D0' => 'D0',
      '00D1' => 'D1',
      '00D2' => 'D2',
      '00D3' => 'D3',
      '00D4' => 'D4',
      '00D5' => 'D5',
      '00D6' => 'D6',
      '00D7' => 'D7',
      '00D8' => 'D8',
      '00D9' => 'D9',
      '00DA' => 'DA',
      '00DB' => 'DB',
      '00DC' => 'DC',
      '00DD' => 'DD',
      '00DE' => 'DE',
      '00DF' => 'DF',
      '00E0' => 'E0',
      '00E1' => 'E1',
      '00E2' => 'E2',
      '00E3' => 'E3',
      '00E4' => 'E4',
      '00E5' => 'E5',
      '00E6' => 'E6',
      '00E7' => 'E7',
      '00E8' => 'E8',
      '00E9' => 'E9',
      '00EA' => 'EA',
      '00EB' => 'EB',
      '00EC' => 'EC',
      '00ED' => 'ED',
      '00EE' => 'EE',
      '00EF' => 'EF',
      '00F0' => 'F0',
      '00F1' => 'F1',
      '00F2' => 'F2',
      '00F3' => 'F3',
      '00F4' => 'F4',
      '00F5' => 'F5',
      '00F6' => 'F6',
      '00F7' => 'F7',
      '00F8' => 'F8',
      '00F9' => 'F9',
      '00FA' => 'FA',
      '00FB' => 'FB',
      '00FC' => 'FC',
      '00FD' => 'FD',
      '00FE' => 'FE',
      '00FF' => 'FF',
   },
   'iso8859_2' => {
      '00A0' => 'A0',
      '0104' => 'A1',
      '02D8' => 'A2',
      '0141' => 'A3',
      '00A4' => 'A4',
      '013D' => 'A5',
      '015A' => 'A6',
      '00A7' => 'A7',
      '00A8' => 'A8',
      '015E' => 'AA',
      '0164' => 'AB',
      '0179' => 'AC',
      '00AD' => 'AD',
      '017D' => 'AE',
      '017B' => 'AF',
      '00B0' => 'B0',
      '0105' => 'B1',
      '02DB' => 'B2',
      '0142' => 'B3',
      '00B4' => 'B4',
      '013E' => 'B5',
      '015B' => 'B6',
      '02C7' => 'B7',
      '00B8' => 'B8',
      '0161' => 'B9',
      '015F' => 'BA',
      '0165' => 'BB',
      '017A' => 'BC',
      '02DD' => 'BD',
      '017E' => 'BE',
      '017C' => 'BF',
      '0154' => 'C0',
      '00C1' => 'C1',
      '00C2' => 'C2',
      '0102' => 'C3',
      '00C4' => 'C4',
      '0139' => 'C5',
      '0106' => 'C6',
      '00C7' => 'C7',
      '010C' => 'C8',
      '00C9' => 'C9',
      '0118' => 'CA',
      '00CB' => 'CB',
      '011A' => 'CC',
      '00CD' => 'CD',
      '00CE' => 'CE',
      '010E' => 'CF',
      '0110' => 'D0',
      '0143' => 'D1',
      '0147' => 'D2',
      '00D3' => 'D3',
      '00D4' => 'D4',
      '0150' => 'D5',
      '00D6' => 'D6',
      '00D7' => 'D7',
      '0158' => 'D8',
      '016E' => 'D9',
      '00DA' => 'DA',
      '0170' => 'DB',
      '00DC' => 'DC',
      '00DD' => 'DD',
      '0162' => 'DE',
      '00DF' => 'DF',
      '0155' => 'E0',
      '00E1' => 'E1',
      '00E2' => 'E2',
      '0103' => 'E3',
      '00E4' => 'E4',
      '013A' => 'E5',
      '0107' => 'E6',
      '00E7' => 'E7',
      '010D' => 'E8',
      '00E9' => 'E9',
      '0119' => 'EA',
      '00EB' => 'EB',
      '011B' => 'EC',
      '00ED' => 'ED',
      '00EE' => 'EE',
      '010F' => 'EF',
      '0111' => 'F0',
      '0144' => 'F1',
      '0148' => 'F2',
      '00F3' => 'F3',
      '00F4' => 'F4',
      '0151' => 'F5',
      '00F6' => 'F6',
      '00F7' => 'F7',
      '0159' => 'F8',
      '016F' => 'F9',
      '00FA' => 'FA',
      '0171' => 'FB',
      '00FC' => 'FC',
      '00FD' => 'FD',
      '0163' => 'FE',
      '02D9' => 'FF',
   },
   'koi8' => {
      '0415' => 'A3',
      '0454' => 'A4',
      '0456' => 'A6',
      '0457' => 'A7',
      '04D7' => 'B3',
      '0404' => 'B4',
      '0406' => 'B6',
      '0407' => 'B7',
      '042E' => 'C0',
      '0430' => 'C1',
      '0431' => 'C2',
      '0446' => 'C3',
      '0434' => 'C4',
      '0435' => 'C5',
      '0444' => 'C6',
      '0433' => 'C7',
      '0445' => 'C8',
      '0438' => 'C9',
      '0439' => 'CA',
      '043A' => 'CB',
      '043B' => 'CC',
      '043C' => 'CD',
      '043D' => 'CE',
      '043E' => 'CF',
      '043F' => 'D0',
      '044F' => 'D1',
      '0440' => 'D2',
      '0441' => 'D3',
      '0442' => 'D4',
      '0443' => 'D5',
      '0436' => 'D6',
      '0432' => 'D7',
      '044C' => 'D8',
      '044B' => 'D9',
      '0437' => 'DA',
      '0448' => 'DB',
      '044D' => 'DC',
      '0449' => 'DD',
      '0447' => 'DE',
      '044A' => 'DF',
      '042D' => 'E0',
      '0410' => 'E1',
      '0411' => 'E2',
      '0426' => 'E3',
      '0414' => 'E4',
      '0415' => 'E5',
      '0424' => 'E6',
      '0413' => 'E7',
      '0425' => 'E8',
      '0418' => 'E9',
      '0419' => 'EA',
      '041A' => 'EB',
      '041B' => 'EC',
      '041C' => 'ED',
      '041D' => 'EE',
      '041E' => 'EF',
      '041F' => 'F0',
      '042F' => 'F1',
      '0420' => 'F2',
      '0421' => 'F3',
      '0422' => 'F4',
      '0423' => 'F5',
      '0416' => 'F6',
      '0412' => 'F7',
      '042C' => 'F8',
      '042B' => 'F9',
      '0417' => 'FA',
      '0428' => 'FB',
      '042D' => 'FC',
      '0429' => 'FD',
      '0427' => 'FE',
      '042A' => 'FF',
   },
);

%eight_bit_to_unicode = ();
foreach my $encoding (keys(%makeinfo_encoding_to_map))
{
   my $unicode_to_eight = $makeinfo_unicode_to_eight_bit{$makeinfo_encoding_to_map{$encoding}};
#print STDERR "$encoding, $makeinfo_encoding_to_map{$encoding}, $unicode_to_eight\n";
   foreach my $utf8_key (keys(%{$unicode_to_eight}))
   {
      $eight_bit_to_unicode{$encoding}->{$unicode_to_eight->{$utf8_key}} =
         $utf8_key;
   }
}

# currently unused
my %makeinfo_transliterate_map = (
  '0416' => 'ZH',
  '0447' => 'ch',
  '00EB' => 'e',
  '0414' => 'D',
  '0159' => 'r',
  '00E6' => 'ae',
  '042B' => 'Y',
  '00FA' => 'u',
  '043B' => 'l',
  '00DE' => 'TH',
  '00D9' => 'U',
  '00C4' => 'A',
  '0148' => 'n',
  '00F6' => 'o',
  '0434' => 'd',
  '041E' => 'O',
  '041B' => 'L',
  '044B' => 'y',
  '0107' => 'c',
  '0415' => 'E',
  '00C1' => 'A',
  '00D3' => 'O',
  '00DB' => 'U',
  '016E' => 'U',
  '013A' => 'l',
  '017B' => 'Z',
  '00F1' => 'n',
  '0428' => 'SH',
  '0153' => 'oe',
  '00F4' => 'o',
  '0144' => 'n',
  '0404' => 'IE',
  '0427' => 'CH',
  '0162' => 'T',
  '017A' => 'z',
  '0448' => 'sh',
  '0436' => 'zh',
  '00F9' => 'u',
  '0406' => 'I',
  '0103' => 'a',
  '0422' => 'T',
  '0160' => 'S',
  '0165' => 't',
  '017E' => 'z',
  '00F0' => 'd',
  '043E' => 'o',
  '043D' => 'n',
  '013E' => 'l',
  '0412' => 'V',
  '0111' => 'd',
  '0155' => 's',
  '017C' => 'z',
  '00CE' => 'I',
  '042D' => 'E',
  '00C8' => 'E',
  '00F8' => 'oe',
  '00F2' => 'o',
  '00FF' => 'y',
  '0420' => 'R',
  '0119' => 'e',
  '00D2' => 'O',
  '043C' => 'm',
  '00D0' => 'DH',
  '0179' => 'Z',
  '0110' => 'D',
  '043F' => 'p',
  '0170' => 'U',
  '011A' => 'E',
  '010C' => 'C',
  '015A' => 'S',
  '0433' => 'g',
  '00E1' => 'a',
  '010D' => 'c',
  '00CC' => 'I',
  '016F' => 'u',
  '0457' => 'yi',
  '00C2' => 'A',
  '0438' => 'i',
  '00E3' => 'a',
  '0435' => 'e',
  '0440' => 'r',
  '042A' => 'W',
  '0431' => 'b',
  '00EE' => 'i',
  '0150' => 'O',
  '00E8' => 'e',
  '0418' => 'I',
  '00CF' => 'I',
  '015F' => 's',
  '0142' => 'l',
  '0147' => 'N',
  '00DF' => 'ss',
  '00E5' => 'aa',
  '00C3' => 'A',
  '0106' => 'C',
  '0141' => 'L',
  '0164' => 'T',
  '017D' => 'Z',
  '00EC' => 'i',
  '041C' => 'M',
  '00C9' => 'E',
  '00E0' => 'a',
  '043A' => 'k',
  '00F5' => 'o',
  '042C' => 'X',
  '0449' => 'shch',
  '0444' => 'f',
  '0139' => 'L',
  '0158' => 'R',
  '00F3' => 'o',
  '00FB' => 'u',
  '0424' => 'F',
  '0446' => 'c',
  '0423' => 'U',
  '0442' => 't',
  '00FD' => 'y',
  '0102' => 'A',
  '0104' => 'A',
  '00CB' => 'E',
  '0426' => 'C',
  '00CD' => 'I',
  '0437' => 'z',
  '0178' => 'y',
  '00D4' => 'O',
  '044D' => 'e',
  '0432' => 'v',
  '013D' => 'L',
  '0163' => 't',
  '0456' => 'i',
  '011B' => 'e',
  '044F' => 'ya',
  '0429' => 'SHCH',
  '0411' => 'B',
  '044A' => 'w',
  '00C6' => 'AE',
  '041D' => 'N',
  '00DA' => 'U',
  '00C0' => 'A',
  '0152' => 'OE',
  '00DD' => 'Y',
  '0154' => 'R',
  '00E9' => 'e',
  '00D5' => 'O',
  '041F' => 'P',
  '0161' => 's',
  '0430' => 'a',
  '0445' => 'h',
  '00E2' => 'a',
  '00D6' => 'O',
  '0407' => 'YI',
  '00CA' => 'E',
  '0439' => 'i',
  '0171' => 'u',
  '00DC' => 'U',
  '042F' => 'YA',
  '0425' => 'H',
  '00FE' => 'th',
  '00D1' => 'N',
  '044C' => 'x',
  '010F' => 'd',
  '0410' => 'A',
  '0443' => 'u',
  '00EF' => 'i',
  '0105' => 'a',
  '00EA' => 'e',
  '00E4' => 'a',
  '015E' => 'S',
  '0417' => 'Z',
  '00ED' => 'i',
  '00FC' => 'u',
  '04D7' => 'IO',
  '00D8' => 'OE',
  '0419' => 'I',
  '0421' => 'S',
  '0143' => 'N',
  '010E' => 'D',
  '0413' => 'G',
  '015B' => 's',
  '0151' => 'o',
  '00E7' => 'c',
  '00C5' => 'AA',
  '0441' => 's',
  '0118' => 'E',
  '00C7' => 'C',
  '041A' => 'K',
  '0454' => 'ie',
  '042E' => 'yu',
);


%transliterate_map = (
               '00C5'  => 'AA',
               '00E5'  => 'aa',
               '00D8'  => 'O',
               '00F8'  => 'o',
               '00E6' => 'ae',
               '0153' => 'oe',
               '00C6' => 'AE',
               '0152' => 'OE',
               '00DF' => 'ss',
               '0141' => 'L',
               '0142' => 'l',
               '00D0' => 'D',
               '00F0' => 'd',
               '00DE' => 'TH',
               '00FE' => 'th',
               '0415'  => 'E',
               '0435'  => 'e',
               '0426'  => 'C',
               '042A'  => 'W',
               '044A'  => 'w',
               '042C'  => 'X',
               '044C'  => 'x',
               '042E'  => 'yu',
               '042F'  => 'YA',
               '044F'  => 'ya',
               '0433'  => 'g',
               '0446'  => 'c',
               '04D7'  => 'IO',
               '00DD'  => 'Y', # unidecode gets this wrong ?
               # following appears in tests, this is required to have
               # the same output with and without unidecode
               '4E2D'  => 'Zhong',
               '6587'  => 'Wen',
               '793A'  => 'Shi',
               '4F8B'  => 'Li',
               '7B2C'  => 'Di',
               '7AE0'  => 'Zhang',
               '53E6'  => 'Ling',
               '4E2A'  => 'Ge',
               # in http://www.cantonese.sheik.co.uk/dictionary/characters/7/
               # unidecode certainly gets it wrong
               '4E00'  => 'Yi',
               'FF08' => '(',
               'FF09' => ')',
               'FF0C' => ',',
               '5B66' => 'Xue',
               '7FD2' => 'Xi',
               '30DE' => 'ma',
               '30CB' => 'ni',
               '30E5' => 'yu',
               '30A2' => 'a',
               '30EB' => 'ru',
          );

foreach my $symbol(keys(%unicode_map))
{
    if ($unicode_map{$symbol} ne '' and !exists($transliterate_map{$symbol}))
    {
         $no_transliterate_map{$unicode_map{$symbol}} = 1;
    }
}

%ascii_character_map = (
            ' ' => '0020',
            '!' => '0021',
            '"' => '0022',
            '#' => '0023',
            '$' => '0024',
            '%' => '0025',
            '&' => '0026',
            "'" => '0027',
            '(' => '0028',
            ')' => '0029',
            '*' => '002A',
            '+' => '002B',
            ',' => '002C',
            '-' => '002D',
            '.' => '002E',
            '/' => '002F',
            ':' => '003A',
            ';' => '003B',
            '<' => '003C',
            '=' => '003D',
            '>' => '003E',
            '?' => '003F',
            '@' => '0040',
            '[' => '005B',
            '\\' => '005C',
            ']' => '005D',
            '^' => '005E',
            '_' => '005F',
            '`' => '0060',
            '{' => '007B',
            '|' => '007C',
            '}' => '007D',
            '~' => '007E',
);

%perl_charset_to_html = (
              'utf8'       => 'utf-8',
              'utf-8-strict'       => 'utf-8',
              'ascii'      => 'us-ascii',
              'shiftjis'      => 'shift_jis',
);

# encoding name normalization to html-compatible encoding names
%t2h_encoding_aliases = (
              'latin1' => 'iso-8859-1',
);

foreach my $perl_charset (keys(%perl_charset_to_html))
{
   $t2h_encoding_aliases{$perl_charset} = $perl_charset_to_html{$perl_charset};
   $t2h_encoding_aliases{$perl_charset_to_html{$perl_charset}} = $perl_charset_to_html{$perl_charset};
}

# These are the encodings from the texinfo manual
foreach my $canonical_encoding('us-ascii', 'utf-8', 'iso-8859-1', 
  'iso-8859-15','iso-8859-2','koi8-r', 'koi8-u')
{
  $canonical_texinfo_encodings{$canonical_encoding} = 1;
}

# not used currently for html, but used in chm.pm
%numeric_entity_map = ();

foreach my $symbol (keys(%unicode_map))
{
    if ($symbol ne '')
    {
        $numeric_entity_map{$symbol} = '&#' . hex($unicode_map{$symbol}) . ';';
    }
}

# When the value begins with & the function with that name is used to do the
# html. The first argument is the text enclosed within {}, the second is the
# style name (which is also the key of the hash)
#
# Otherwithe the value is the html element used to enclose the text, and if
# there is a " the resulting text is also enclosed within `'
my %old_style_map = (
      'acronym',    '',
      'asis',       '',
      'b',          'b',
      'cite',       'cite',
      'clicksequence', '',
      'code',       'code',
      'command',    'code',
      'ctrl',       '&default_ctrl', 
      'dfn',        'em', 
      'dmn',        '',   
      'email',      '&default_email', 
      'emph',       'em',
      'env',        'code',
      'file',       '"tt', 
      'i',          'i',
      'kbd',        'kbd',
      'key',        'kbd',
      'math',       'em',
      'option',     '"samp', 
      'r',          '',
      'samp',       '"samp', 
      'sc',         '&default_sc',
      'strong',     'strong',
      't',          'tt',
      'uref',       '&default_uref',
      'url',        '&default_url',
      'var',        'var',
      'verb',       'tt',
      'titlefont',  '&default_titlefont',
      'w',          '',
     );

sub t2h_default_copy_style_map ($$;$)
{
  my $from = shift;
  my $to = shift;
  my $merge = shift;

  foreach my $command (keys(%$from))
  {
     $to->{$command} = {} if (!exists($to->{$command}));
     foreach my $key (keys(%{$from->{$command}}))
     {
        next if (exists($to->{$command}->{$key}) and $merge);
        if ($key eq 'args')
        {
           $to->{$command}->{$key} = [ @{$from->{$command}->{$key}} ];
        }
        else
        {
           $to->{$command}->{$key} = $from->{$command}->{$key};
        }
     }
  }
}

# default is {'args' => ['normal'], 'attribute' => ''},   
%style_map = (
      'asis',       {},
      'b',          {},
      'cite',       {},
      'clicksequence', {},
      'click',      {'function' => \&t2h_default_click_normal, 'type' => 'simple_style'},
      'code',       {'args' => ['code']},
      'command',    {'args' => ['code']},
      'ctrl',       {'function' => \&t2h_default_ctrl,'type' => 'simple_style'}, 
      'dfn',        {}, 
      'dmn',        {'type' => 'simple_style'},   
      'email',      {'args' => ['code', 'normal'], 
                       'function' => \&t2h_default_email,
                       'type' => 'simple_style'}, 
      #'email',      {'args' => ['normal', 'normal'], 
      #                 'function' => \&t2h_default_email}, 
      'emph',       {}, 
      'env',        {'args' => ['code']},
      'file',       {'args' => ['code'], 'quote' => '"'},
      'headitemfont', {},
      'i',          {},
      'slanted',    {},
      'sansserif',  {},
      'kbd',        {'args' => ['code'], },
      'key',        {'args' => ['code'], 'begin' => '<', 'end' => '>'},
      'math',       {'function' => \&t2h_default_math, 'args' => ['math'] },
      'option',     {'args' => ['code'], 'quote' => '"'},
      'r',          {},
      'samp',       {'args' => ['code'],  'quote' => '"'},
#      'sc',         {'function' => \&t2h_default_sc},
      'sc',         {},
      'strong',     {},
      't',          {},
      'uref',       {'function' => \&t2h_default_uref, 
                      'args' => ['code', 'normal', 'normal'],
                      'type' => 'simple_style' },
      #'uref',       {'function' => \&t2h_default_uref, 
      #                'args' => ['normal', 'normal', 'normal']},
      'url',        {'function' => \&t2h_default_uref, 
                      'args' => ['code', 'normal', 'normal'],
                      'type' => 'simple_style'},
      'indicateurl', {'args' => ['code'], 'begin' => '<', 'end' => '>','type' => 'simple_style'},
      'var',        {},
      'verb',       {'args' => ['code'], },
      'titlefont',  {'function' => \&t2h_default_titlefont, 
            'type' => 'simple_style'},
      'w',          {},
      'hyphenation', {'function' => \&t2h_default_hyphenation, 'args' => ['keep']},
     );

%command_type = ();

foreach my $style (keys(%style_map))
{
   if (exists($style_map{$style}->{'type'}))
   {
       $command_type{$style} = $style_map{$style}->{'type'};
   }
   else
   {
       $command_type{$style} = 'style';
   }
}


sub t2h_default_select_substitution($$$)
{
   my $in_raw_text = shift;
   my $in_preformatted = shift;
   my $in_simple = shift;
   
   if ($in_raw_text)
   {
      return \@text_substitutions_texi;
   }
   elsif ($in_simple)
   {
      return \@text_substitutions_simple_format;
   }
   elsif ($in_preformatted)
   {
      return \@text_substitutions_pre;
   }
   else
   {
      return \@text_substitutions_normal;
   }
}

sub t2h_text_substitutions($$$$)
{
   my $text = shift;
   my $in_raw_text = shift;
   my $in_preformatted = shift;
   my $in_simple = shift;
   
   my $substitutions = t2h_default_select_substitution($in_raw_text, $in_preformatted, $in_simple);
   foreach my $substitution_entry (@$substitutions)
   {
      my $from = quotemeta($substitution_entry->[0]);
      my $to = $substitution_entry->[1];
      $text =~ s/$from/$to/g;
   }
   return $text;
}

sub t2h_add_text_substitutions($$$$$)
{
   my $entry = shift;
   my $in_normal = shift;
   my $in_raw_text = shift;
   my $in_preformatted = shift;
   my $in_simple = shift;

   my @formats_to_be_done = ($in_normal, $in_raw_text, $in_preformatted, $in_simple);

   for (my $index = 0; $index < scalar(@formats_to_be_done); $index++)
   {
       next unless ($formats_to_be_done[$index]);
       my @args = (0, 0, 0);
       my $found = 0;
       $args[$index -1] = 1 if ($index > 0);
       my $substitutions = &t2h_default_select_substitution(@args);
       foreach my $substitution_entry (@$substitutions)
       {
           if ($substitution_entry->[0] eq $entry->[0])
           {
               $found = 1;
               $substitution_entry->[1] = $entry->[1];
           }
       }
       push @$substitutions, $entry unless ($found);
   }
}

sub t2h_remove_text_substitutions($$$$$)
{
   my $entry = shift;
   my $in_normal = shift;
   my $in_raw_text = shift;
   my $in_preformatted = shift;
   my $in_simple = shift;

   my @formats_to_be_done = ($in_normal, $in_raw_text, $in_preformatted, $in_simple);

   for (my $index = 0; $index < scalar(@formats_to_be_done); $index++)
   {
       next unless ($formats_to_be_done[$index]);
       my @args = (0, 0, 0);
       $args[$index -1] = 1 if ($index > 0);
       my $substitutions = &t2h_default_select_substitution(@args);

       @$substitutions = grep {$_->[0] ne $entry} @$substitutions;
   }
}


%unicode_diacritical = (
       'H'          => '030B', 
       'ringaccent' => '030A', 
       "'"          => '0301',
       'v'          => '030C', 
       ','          => '0327', 
       '^'          => '0302', 
       'dotaccent'  => '0307',
       '`'          => '0300',
       '='          => '0304', 
       '~'          => '0303',
       '"'          => '0308', 
       'udotaccent' => '0323', 
       'ubaraccent' => '0332', 
       'u'          => '0306',
       'tieaccent'  => '0361',
       'ogonek'     => '0328'
);

%unicode_accents = (
    'dotaccent' => { # dot above
        'A' => '0226', #C moz-1.2 
        'a' => '0227', #c moz-1.2
        'B' => '1E02',
        'b' => '1E03',
        'C' => '010A',
        'c' => '010B',
        'D' => '1E0A',
        'd' => '1E0B',
        'E' => '0116',
        'e' => '0117',
        'F' => '1E1E',
        'f' => '1E1F',
        'G' => '0120',
        'g' => '0121',
        'H' => '1E22',
        'h' => '1E23',
        'i' => '0069',
        'I' => '0130',
        'N' => '1E44',
        'n' => '1E45',
        'O' => '022E', #Y moz-1.2
        'o' => '022F', #v moz-1.2
        'P' => '1E56',
        'p' => '1E57',
        'R' => '1E58',
        'r' => '1E59',
        'S' => '1E60',
        's' => '1E61',
        'T' => '1E6A',
        't' => '1E6B',
        'W' => '1E86',
        'w' => '1E87',
        'X' => '1E8A',
        'x' => '1E8B',
        'Y' => '1E8E',
        'y' => '1E8F',
        'Z' => '017B',
        'z' => '017C',
    },
    'udotaccent' => { # dot below
        'A' => '1EA0',
        'a' => '1EA1',
        'B' => '1E04',
        'b' => '1E05',
        'D' => '1E0C',
        'd' => '1E0D',
        'E' => '1EB8',
        'e' => '1EB9',
        'H' => '1E24',
        'h' => '1E25',
        'I' => '1ECA',
        'i' => '1ECB',
        'K' => '1E32',
        'k' => '1E33',
        'L' => '1E36',
        'l' => '1E37',
        'M' => '1E42',
        'm' => '1E43',
        'N' => '1E46',
        'n' => '1E47',
        'O' => '1ECC',
        'o' => '1ECD',
        'R' => '1E5A',
        'r' => '1E5B',
        'S' => '1E62',
        's' => '1E63',
        'T' => '1E6C',
        't' => '1E6D',
        'U' => '1EE4',
        'u' => '1EE5',
        'V' => '1E7E',
        'v' => '1E7F',
        'W' => '1E88',
        'w' => '1E89',
        'Y' => '1EF4',
        'y' => '1EF5',
        'Z' => '1E92',
        'z' => '1E93',
    },
    'ubaraccent' => { # line below
        'B' => '1E06',
        'b' => '1E07',
        'D' => '1E0E',
        'd' => '1E0F',
        'h' => '1E96',
        'K' => '1E34',
        'k' => '1E35',
        'L' => '1E3A',
        'l' => '1E3B',
        'N' => '1E48',
        'n' => '1E49',
        'R' => '1E5E',
        'r' => '1E5F',
        'T' => '1E6E',
        't' => '1E6F',
        'Z' => '1E94',
        'z' => '1E95',
    },
    ',' => { # cedilla
        'C' => '00C7',
        'c' => '00E7',
        'D' => '1E10',
        'd' => '1E11',
        'E' => '0228', #C moz-1.2
        'e' => '0229', #c moz-1.2
        'G' => '0122',
        'g' => '0123',
        'H' => '1E28',
        'h' => '1E29',
        'K' => '0136',
        'k' => '0137',
        'L' => '013B',
        'l' => '013C',
        'N' => '0145',
        'n' => '0146',
        'R' => '0156',
        'r' => '0157',
        'S' => '015E',
        's' => '015F',
        'T' => '0162',
        't' => '0163',
    },
    '=' => { # macron
        'A' => '0100',
        'a' => '0101',
        'E' => '0112',
        'e' => '0113',
        'I' => '012A',
        'i' => '012B',
        'G' => '1E20',
        'g' => '1E21',
        'O' => '014C',
        'o' => '014D',
        'U' => '016A',
        'u' => '016B',
        'Y' => '0232', #? moz-1.2
        'y' => '0233', #? moz-1.2
    },
    '"' => { # diaeresis
        'A' => '00C4',
        'a' => '00E4',
        'E' => '00CB',
        'e' => '00EB',
        'H' => '1E26',
        'h' => '1E27',
        'I' => '00CF',
        'i' => '00EF',
        'O' => '00D6',
        'o' => '00F6',
        't' => '1E97',
        'U' => '00DC',
        'u' => '00FC',
        'W' => '1E84',
        'w' => '1E85',
        'X' => '1E8C',
        'x' => '1E8D',
        'y' => '00FF',
        'Y' => '0178',
    },
    'u' => { # breve
        'A' => '0102',
        'a' => '0103',
        'E' => '0114',
        'e' => '0115',
        'G' => '011E',
        'g' => '011F',
        'I' => '012C',
        'i' => '012D',
        'O' => '014E',
        'o' => '014F',
        'U' => '016C',
        'u' => '016D',
    },
    "'" => { # acute
        'A' => '00C1',
        'a' => '00E1',
        'C' => '0106',
        'c' => '0107',
        'E' => '00C9',
        'e' => '00E9',
        'G' => '01F4',
        'g' => '01F5',
        'I' => '00CD',
        'i' => '00ED',
        'K' => '1E30',
        'k' => '1E31',
        'L' => '0139',
        'l' => '013A',
        'M' => '1E3E',
        'm' => '1E3F',
        'N' => '0143',
        'n' => '0144',
        'O' => '00D3',
        'o' => '00F3',
        'P' => '1E54',
        'p' => '1E55',
        'R' => '0154',
        'r' => '0155',
        'S' => '015A',
        's' => '015B',
        'U' => '00DA',
        'u' => '00FA',
        'W' => '1E82',
        'w' => '1E83',
        'Y' => '00DD',
        'y' => '00FD',
        'Z' => '0179',
        'z' => '018A',
    },
    '~' => { # tilde
        'A' => '00C3',
        'a' => '00E3',
        'E' => '1EBC',
        'e' => '1EBD',
        'I' => '0128',
        'i' => '0129',
        'N' => '00D1',
        'n' => '00F1',
        'O' => '00D5',
        'o' => '00F5',
        'U' => '0168',
        'u' => '0169',
        'V' => '1E7C',
        'v' => '1E7D',
        'Y' => '1EF8',
        'y' => '1EF9',
    },
    '`' => { # grave
        'A' => '00C0',
        'a' => '00E0',
        'E' => '00C8',
        'e' => '00E8',
        'I' => '00CC',
        'i' => '00EC',
        'N' => '01F8',
        'n' => '01F9',
        'O' => '00D2',
        'o' => '00F2',
        'U' => '00D9',
        'u' => '00F9',
        'W' => '1E80',
        'w' => '1E81',
        'Y' => '1EF2',
        'y' => '1EF3',
    },
    '^' => { # circumflex
        'A' => '00C2',
        'a' => '00E2',
        'C' => '0108',
        'c' => '0109',
        'E' => '00CA',
        'e' => '00EA',
        'G' => '011C',
        'g' => '011D',
        'H' => '0124',
        'h' => '0125',
        'I' => '00CE',
        'i' => '00EE',
        'J' => '0134',
        'j' => '0135',
        'O' => '00D4',
        'o' => '00F4',
        'S' => '015C',
        's' => '015D',
        'U' => '00DB',
        'u' => '00FB',
        'W' => '0174',
        'w' => '0175',
        'Y' => '0176',
        'y' => '0177',
        'Z' => '1E90',
        'z' => '1E91',
    },
    'ringaccent' => { # ring
        'A' => '00C5',
        'a' => '00E5',
        'U' => '016E',
        'u' => '016F',
        'w' => '1E98',
        'y' => '1E99',
    },
    'v' => { # caron
        'A' => '01CD',
        'a' => '01CE',
        'C' => '010C',
        'c' => '010D',
        'D' => '010E',
        'd' => '010F',
        'E' => '011A',
        'e' => '011B',
        'G' => '01E6',
        'g' => '01E7',
        'H' => '021E', #K with moz-1.2
        'h' => '021F', #k with moz-1.2
        'I' => '01CF',
        'i' => '01D0',
        'K' => '01E8',
        'k' => '01E9',
        'L' => '013D', #L' with moz-1.2
        'l' => '013E', #l' with moz-1.2
        'N' => '0147',
        'n' => '0148',
        'O' => '01D1',
        'o' => '01D2',
        'R' => '0158',
        'r' => '0159',
        'S' => '0160',
        's' => '0161',
        'T' => '0164',
        't' => '0165',
        'U' => '01D3',
        'u' => '01D4',
        'Z' => '017D',
        'z' => '017E',
    },
    'H' => { # double acute
        'O' => '0150',
        'o' => '0151',
        'U' => '0170',
        'u' => '0171',
    },
    'ogonek' => {
        'A' => '0104',
        'a' => '0105',
        'E' => '0118',
        'e' => '0119',
        'I' => '012E',
        'i' => '012F',
        'U' => '0172',
        'u' => '0173',
        'O' => '01EA',
        'o' => '01EB',
    },
);

foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
{
     $style_map{$accent_command} = { 'function' => \&t2h_default_accent };
     $old_style_map{$accent_command} = '&default_accent';
     $style_map_texi{$accent_command} = { 'function' => \&t2h_default_accent };
}


%transliterate_accent_map = ();
foreach my $command (keys(%unicode_accents))
{
    foreach my $letter(keys (%{$unicode_accents{$command}}))
    {
        $transliterate_accent_map{$unicode_accents{$command}->{$letter}}
            = $letter 
          unless (exists($transliterate_map{$unicode_accents{$command}->{$letter}}));
    }
}

sub default_accent($$)
{
    my $text = shift;
    my $accent = shift;
    return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
    return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
    return $text . '&lt;' if ($accent eq 'v');
    return ascii_accents($text, $accent);
}

sub t2h_default_accent($$)
{
    my $accent = shift;
    my $args = shift;

    my $text = $args->[0];

    return ascii_accents($text, $accent);
}

####################################################################
# special accent/encoding commands
#
# Some functions used to override normal formatting functions in specific 
# cases. The user shouldn't want to change them, but can use them.
#

sub ascii_accents($$)
{
    my $text = shift;
    my $accent = shift;
    return $text if ($accent eq 'dotless');
    return $text . "''" if ($accent eq 'H');
    return $text . '.' if ($accent eq 'dotaccent');
    return $text . '*' if ($accent eq 'ringaccent');
    return $text . '[' if ($accent eq 'tieaccent');
    return $text . '(' if ($accent eq 'u');
    return $text . '_' if ($accent eq 'ubaraccent');
    return '.' . $text  if ($accent eq 'udotaccent');
    return $text . '<' if ($accent eq 'v');
    return $text . ';' if ($accent eq 'ogonek');
    return $text . $accent if (defined($accent_map{$accent}));
}

sub xml_default_accent($$)
{
    my $accent = shift;
    my $args = shift;

    my $text = $args->[0];

    return "&${text}$accent_map{$accent};" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
    return '&' . $text . 'ring;' if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
    return $text . '&lt;' if ($accent eq 'v');
# FIXME here there could be a conversion to the character in the right 
# encoding, like 
#    if (get_conf('USE_UNICODE') and defined($OUT_ENCODING) and $OUT_ENCODING ne '' 
#        and exists($unicode_accents{$accent}) and  exists($unicode_accents{$accent}->{$text}))
#    {
#          my $encoded_char =  Encode::encode($OUT_ENCODING, chr(hex($unicode_map{$thing})), Encode::FB_QUIET);
#          return $encoded_char if ($encoded_char ne '');
#    }
    if (get_conf('USE_NUMERIC_ENTITY'))
    {
        if (exists($unicode_accents{$accent}) and exists($unicode_accents{$accent}->{$text}))
        {
             return ('&#' . hex($unicode_accents{$accent}->{$text}) . ';');
        }
    }
    return ascii_accents($text, $accent);
}

# used to utf8 encode the result
sub t2h_utf8_accent($$$)
{
    my $accent = shift;
    my $args = shift;
    my $style_stack = shift;
  
    my $text = $args->[0];
    #print STDERR "$accent\[".scalar(@$style_stack) ."\] (@$style_stack)\n"; 

    # special handling of @dotless{i}
    if ($accent eq 'dotless')
    { 
        if (($text eq 'i') and (!defined($style_stack->[-1]) or (!defined($unicode_accents{$style_stack->[-1]})) or ($style_stack->[-1] eq 'tieaccent')))
        {
             return "\x{0131}";
        }
        #return "\x{}" if ($text eq 'j'); # not found !
        return $text;
    }
        
    # FIXME \x{0131}\x{0308} for @dotless{i} @" doesn't lead to NFC 00ef.
    return Unicode::Normalize::NFC($text . chr(hex($unicode_diacritical{$accent}))) 
        if (defined($unicode_diacritical{$accent}));
    return ascii_accents($text, $accent);
}

sub t2h_utf8_normal_text($$$$$$$;$)
{
    my $text = shift;
    my $in_raw_text = shift;
    my $in_preformatted = shift;
    my $in_code = shift;
    my $in_math = shift;
    my $in_simple = shift;
    my $style_stack = shift;
    my $state = shift;

    $text = &$protect_text($text) unless($in_raw_text);
    $text = uc($text) if (in_small_caps($style_stack));

    if (!$in_code and !$in_preformatted)
    {
        $text =~ s/---/\x{2014}/g;
        $text =~ s/--/\x{2013}/g;
        $text =~ s/``/\x{201C}/g;
        $text =~ s/''/\x{201D}/g;
    }
    $text = t2h_text_substitutions($text, $in_raw_text, ($in_preformatted or $in_code), $in_simple);
    return Unicode::Normalize::NFC($text);
}

sub t2h_enable_encoding_normal_accent($$$)
{
  return t2h_enable_encoding_accent ('normal', @_);
}
sub t2h_enable_encoding_texi_accent($$$)
{
  return t2h_enable_encoding_accent ('texi', @_);
}
sub t2h_enable_encoding_pre_accent($$$)
{
  return t2h_enable_encoding_accent ('pre', @_);
}

sub t2h_enable_encoding_accent($$$$)
{
  my $context = shift;
  my @other_args = @_;

  my $accent = shift;
  my $args = shift;
  my $style_stack = shift;
  my $text = $args->[0];

#print STDERR "enable_encoding_accent called($context) $accent (@$style_stack)\n";

  # in case ENCODING_NAME is not known, the accent functions saved previously
  # are used. 
  # This should happen rarely, like during @setfilename parsing.
  return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args) if (!defined(get_conf('ENCODING_NAME')));

  return t2h_utf8_accent($accent,[$text],$style_stack) if (get_conf('ENCODING_NAME') eq 'utf-8');

  # use the saved default handling if this is not a known 8 bit encoding
  return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args) if (!exists($makeinfo_encoding_to_map{get_conf('ENCODING_NAME')}));

  # the following is for the handling of known 8 bit encodings.
  if (scalar(@t2h_enable_encoding_accents_stack))
  {
    # in that case, we already have a result ready that corresponds with the
    # formatting of a part of the stack mapped to 
    # t2h_enable_encoding_accents_stack, so it is emptied and the innermost
    # $text is returned as is, such that the unmodified already formatted 
    # innermost formatted accented text is returned.

    #print STDERR " doing nothing, still in stack (@t2h_enable_encoding_accents_stack), accent: $accent";
    my $stack_accent = shift @t2h_enable_encoding_accents_stack;
    #print STDERR " stack_accent $stack_accent\n";
    return $text;
  }

  # in that case there is no t2h_enable_encoding_accents_stack, so we are 
  # at the closing of the innermost accented command. We will try to format 
  # all the stack in reverse(@$style_stack) that coresponds with 
  # accent commands
  my @accents_stack = ();
  my @styles = reverse(@$style_stack);

  # accents are formatted and the intermediate results are kept, such
  # that we can return the maximum of multiaccented letters that can be
  # rendered with a given eight bit formatting.

  # first put the letter in the stack
  my @utf8_partial_results = { 'result' => $text, 
      'accents_stack' => [ @accents_stack ]};

  # then the accent that is associated with the function call
  my $current_accent = t2h_utf8_accent($accent,[$text],$style_stack);
  @accents_stack = ($accent);
  push @utf8_partial_results, { 'result' => $current_accent,
       'accents_stack' => [ @accents_stack ]};

  # and then all the other accents on the stack
  while (scalar(@styles) and (defined($unicode_accents{$styles[0]}) or $styles[0] eq 'dotless'))
  {
    my $next_style = shift @styles;
    my @new_stack = reverse(@styles);
    $current_accent = t2h_utf8_accent($next_style,[$current_accent],\@new_stack);
    push @accents_stack, $next_style;
    push @utf8_partial_results, { 'result' => $current_accent,
       'accents_stack' => [ @accents_stack ]}
        ;
  }

  my $enc_map = $makeinfo_encoding_to_map{get_conf('ENCODING_NAME')};
  my $eight_bit;
  my $result;
  # At this point we have the utf8 encoded results for the accent
  # commands stack, with all the intermediate results.
  # For each one we'll check if it is possible to encode it in the 
  # current eight bit output encoding table
  foreach my $partial_result (@utf8_partial_results)
  {
    my $char = $partial_result->{'result'};
    my $new_eight_bit = '';
    my $new_codepoint;
   
    if (ord($char) <= 128)
    {
      $new_eight_bit =  uc(sprintf("%02x",ord($char)));
      $new_codepoint = uc(sprintf("%04x",ord($char)));
    }
    elsif (ord($char) <= hex(0xFFFF))
    {
      $new_codepoint = uc(sprintf("%04x",ord($char)));
      if (exists($makeinfo_unicode_to_eight_bit{$enc_map}->{$new_codepoint}))
      {
         $new_eight_bit = $makeinfo_unicode_to_eight_bit{$enc_map}->{$new_codepoint};
      }
    }
    #my $eight_bit_txt = 'undef';
    #$eight_bit_txt = $eight_bit if (defined($eight_bit));
    #print STDERR "" . Encode::encode('utf8', "$char") . " (@{$partial_result->{'accents_stack'}}), new_codepoint: $new_codepoint 8bit: $new_eight_bit old:$eight_bit_txt\n";
    # no corresponding eight bit character found
    last if ($new_eight_bit eq '');

    # in that case, the new eight bit character is the same than the one 
    # found with one less character (and it isnt a @dotless{i}). It may
    # mean 2 things
    # -> there are 2 characters in accent. This could happen, for example
    #    if an accent that cannot be rendered is found and it leads to 
    #    appending or prepending a character. For example this happens for
    #    @={@,{@~{n}}}, where @,{@~{n}} is expanded to a 2 character:
    #    n with a tilde, followed by a , 
    #    In nthat case, the additional utf8 accent is prepended, which 
    #    means that it is composed with the , and leaves n with a tilde 
    #    untouched. 
    # -> ord(char) leads to the same for the more inner character.
    #    this, for example, happens for @ubaraccent{a}, where ord(a) is
    #    the same than ord(a with underbar).
    last if (defined($eight_bit) and (($new_eight_bit eq $eight_bit) 
       and !($partial_result->{'accents_stack'}[0] eq 'dotless' and $char eq 'i')));
    $result = $partial_result;
    $eight_bit = $new_eight_bit;
  }
  if (defined($result) and scalar(@{$result->{'accents_stack'}}))
  {
     # we got a result, return it and put in t2h_enable_encoding_accents_stack
     # the stack of accent commands that were processed. They wont be used
     # further, but only unshifted.

  #print STDERR "Result: ".Encode::encode('utf8', $result->{'result'}) ." '$eight_bit' (@{$result->{'accents_stack'}})\n" if defined($result);
     @t2h_enable_encoding_accents_stack = @{$result->{'accents_stack'}};
     # remove the first, it is the accent being processed
     shift @t2h_enable_encoding_accents_stack;
     # it should be noted that we return the 'utf8' accent (which is really
     # a codepoint, and not the eight bit representation, we leave the 
     # conversion to perl, which should handle it fine
     return $result->{'result'};
  }
  
  return &{$t2h_enable_encoding_default_accent{$context}->{$accent}}(@other_args);
}

# end special accent/encoding commands
####################################################################

####################################################################
# TeX/LaTeX, that can especially be used in @math
# To load the appropriate hash, use
# default_load_tex_math

my %tex_default_simple_map_math = (
 '{' => '\{',
 '}' => '\}',
 '\\' => '\\'
);

my %tex_default_math_things_map = %default_things_map;

$tex_default_math_things_map{'bullet'} = '\bullet';
$tex_default_math_things_map{'copyright'} = '\copyright';
$tex_default_math_things_map{'registeredsymbol'} = '\circledR';
$tex_default_math_things_map{'dots'} = '\dots';
$tex_default_math_things_map{'endots'} = '\dots';
$tex_default_math_things_map{'equiv'} = '\equiv';
$tex_default_math_things_map{'expansion'} = '\mapsto';
$tex_default_math_things_map{'arrow'} = '\rightarrow';
$tex_default_math_things_map{'point'} = '\star';
$tex_default_math_things_map{'print'} = '\dashv';
$tex_default_math_things_map{'result'} = '\Rightarrow';
$tex_default_math_things_map{'pounds'} = '\pounds';
$tex_default_math_things_map{'geq'} = '\geq';
$tex_default_math_things_map{'leq'} = '\leq';
$tex_default_math_things_map{'textdegree'} = '^\circ';

my %latex_default_math_things_map = %tex_default_math_things_map;

$latex_default_math_things_map{'aa'} = '\mathring{a}';
$latex_default_math_things_map{'AA'} = '\mathring{A}';

# FIXME Maybe this should not be there since it is not for math but
# more for a completly separate format.
my %latex_default_things_map;

foreach my $thing (keys(%default_things_map))
{
    $latex_default_things_map{$thing} = '\\'.$thing;
}

$latex_default_things_map{'error'} = '\fbox{error}';
$latex_default_things_map{'enddots'} = '\dots\@';
$latex_default_things_map{'exclamdown'} = '\textexclamdown';
$latex_default_things_map{'questiondown'} = '\textquestiondown';
$latex_default_things_map{'tie'} = '~';
$latex_default_things_map{'registeredsymbol'} = '\textregistered';
$latex_default_things_map{'ordf'} = '\textordfeminine';
$latex_default_things_map{'ordm'} = '\textordmasculine';
$latex_default_things_map{'guillemetleft'} = '\guillemotleft';
$latex_default_things_map{'guillemetright'} = '\guillemotright';

foreach my $text_prefixed_symbols ('bullet', 'exclamdown', 'questiondown', 
   'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright')
{
   $latex_default_things_map{$text_prefixed_symbols} = '\text'.$text_prefixed_symbols;
}

foreach my $math_only ('equiv', 'expansion', 'arrow', 'minus', 'point',
   'print', 'result', 'geq', 'leq')
{
   $latex_default_things_map{$math_only} = '$'.$latex_default_math_things_map{$math_only}.'$';
}


# End TeX/LaTeX
#############################################################

sub default_sc($$)
{
    return uc($_[0]);
}

sub default_ctrl($$)
{
   return "^$_[0]";
}

# obsolete, no warning, but noop
sub t2h_default_ctrl($$$)
{
    shift;
    my $args = shift;
    #return "^$args->[0]";
    return "$args->[0]";
}

sub default_sc_pre($$)
{
    return uc($_[0]);
}

sub default_titlefont($$)
{
    return "<h1 class=\"titlefont\">$_[0]</h1>" if ($_[0] =~ /\S/);
    return '';
}

# Return nothing if the text is empty
sub t2h_default_titlefont($$$)
{
    shift;
    my $args = shift;
    my $heading = $args->[0];
    return '' unless ($heading =~ /\S/);
    return &$heading_text('@titlefont', $heading, 0);
}

# At some point in time (before 4.7?) according to the texinfo 
# manual, url shouldn't lead to a link but rather be formatted 
# like text. It is now what indicateurl do, url is the same that
# uref with one arg. If we did like makeinfo did it would have been
#sub url($$)
#{
#    return '&lt;<code>' . $_[0] . '</code>&gt;';
#}
# 
# This is unused, t2h_default_uref is used instead
sub t2h_default_url ($$)
{
    shift;
    my $args = shift;
    my $url = shift @$args;
    $url = main::normalise_space($url);
    return '' unless ($url =~ /\S/);
    return t2h_default_url_and_text($url);
}

sub default_url ($$)
{
    my $url = shift;
    my $command = shift;
    $url =~ s/\s*$//;
    $url =~ s/^\s*//;
    return t2h_default_url_and_text($url);
}

sub default_uref($$)
{
    my $arg = shift;
    my $command = shift;
    my ($url, $text, $replacement);
    ($url, $text, $replacement) = split /,\s*/, $arg;
    $url =~ s/\s*$//;
    $url =~ s/^\s*//;
    $text = $replacement if (defined($replacement));
    return t2h_default_url_and_text($url, $text);
}

sub t2h_default_uref($$)
{
    shift;
    my $args = shift;
    my $url = shift @$args;
    my $text = shift @$args;
    my $replacement = shift @$args;
    $url = main::normalise_space($url);
    $replacement = '' if (!defined($replacement));
    $replacement = main::normalise_space($replacement);
    $text = '' if (!defined($text));
    $text = main::normalise_space($text);
    $text = $replacement if ($replacement ne '');
    return t2h_default_url_and_text($url, $text);
}

sub t2h_default_math($$)
{
    shift;
    my $args = shift;
    my $text = shift @$args;
    return "$text";
}

sub default_email($$)
{
    my $arg = shift;
    my $command = shift;
    my ($mail, $text);
    ($mail, $text) = split /,\s*/, $arg;
    $mail =~ s/\s*$//;
    $mail =~ s/^\s*//;
    return t2h_default_url_and_text("mailto:$mail", $text);
}

sub t2h_default_email($$)
{
    my $command = shift;
    my $args = shift;
    my $mail = shift @$args;
    my $text = shift @$args;
    $mail = main::normalise_space($mail);
    if (defined($text))
    {
        $text = main::normalise_space($text);
    }
    my $mailto = '';
    $mailto = "mailto:$mail" if ($mail ne '');
    return t2h_default_url_and_text($mailto, $text);
}

sub t2h_default_click_normal($$$)
{
    return t2h_default_click('normal', @_);
}

sub t2h_default_click_pre($$$)
{
    return t2h_default_click('pre', @_);
}

sub t2h_default_click_texi($$$)
{
    return t2h_default_click('texi', @_);
}

sub t2h_default_click($$$$$)
{
    my $context = shift;
    my $command = shift;
    my $args = shift;
    my $arg = shift @$args;
    my $cmd = get_conf('clickstyle');
    $cmd = 'arrow' if (!defined($cmd) or ($cmd eq ''));

    my $hash = \%things_map;
    if ($context eq 'pre')
    {
        $hash = \%pre_map;
    }
    elsif ($context eq 'texi')
    {
        $hash = \%texi_map;
    }
    return $hash->{$cmd} . $arg if (exists($hash->{$cmd}));
    return $arg;
}

sub t2h_default_hyphenation($$)
{
    my $command = shift;
    my $args = shift;
    my $text = shift @$args;
    $text =~ s/^\s*//;
    $text =~ s/\s*$//;
    my @list = split /\s+/, $text;
    foreach my $entry (@list)
    {
         my $word = $entry;
         $word =~ s/-//g;
         $Texi2HTML::THISDOC{'hyphenation'}->{$word} = $entry;
    }
}

sub t2h_default_no_texi_email
{
    my $command = shift;
    my $args = shift;
    my $mail = shift @$args;
    my $text = shift @$args;
    $mail = main::normalise_space($mail);
    if (defined($text))
    {
        $text = main::normalise_space($text);
    }
    return $text if (defined($text) and ($text ne ''));
    return $mail;
}

sub t2h_default_no_texi_image($$$$)
{
    my $command = shift;
    my $args = shift;
    my $file = $args->[0];
    $file = main::trim_around_spaces($file);
    return main::substitute_line($file, "\@$command", {'remove_texi' => 1, 'code_style' => 1});
}

sub t2h_default_no_texi_acronym_like($$)
{
    my $command = shift;
    my $args = shift;
    my $acronym_texi = $args->[0];
    return (main::remove_texi($acronym_texi)); 
}

sub t2h_remove_command($$$$)
{
    return '';
}

# This is used for style in preformatted sections
my %old_style_map_pre = %old_style_map;
$old_style_map_pre{'sc'} = '&default_sc_pre';
$old_style_map_pre{'titlefont'} = '';

foreach my $command (keys(%style_map))
{
    $style_map_texi{$command} = {} if (!exists($style_map_texi{$command}));
    $style_map_texi{$command}->{'args'} = [ @{$style_map{$command}->{'args'}} ]
        if (exists($style_map{$command}->{'args'}));
 #print STDERR "COMMAND $command";
}

%style_map_pre = ();

t2h_default_copy_style_map(\%style_map, \%style_map_pre);

$style_map_pre{'sc'} = {};
$style_map_pre{'titlefont'} = {};
$style_map_pre{'click'}->{'function'} = \&t2h_default_click_pre;

$style_map_texi{'sc'} = {};
$style_map_texi{'email'}->{'function'} = \&t2h_default_no_texi_email;
$style_map_texi{'click'}->{'function'} = \&t2h_default_click_texi;

####### special styles. You shouldn't need to change them
%special_style = (
           #'xref'      => ['keep','normal','normal','keep','normal'],
           'xref'         => { 'args' => ['keep','keep','keep','keep','keep'],
               'function' => \&main::do_xref },
           'ref'         => { 'args' => ['keep','keep','keep','keep','keep'],
               'function' => \&main::do_xref },
           'pxref'         => { 'args' => ['keep','keep','keep','keep','keep'],
               'function' => \&main::do_xref },
           'inforef'      => { 'args' => ['keep','keep','keep'], 
               'function' => \&main::do_xref },
           'image'        => { 'args' => ['keep','keep','keep','keep','keep'], 'function' => \&main::do_image },
           'anchor'       => { 'args' => ['keep'], 'function' => \&main::do_anchor_label },
           'footnote'     => { 'args' => ['keep'], 'function' => \&main::do_footnote },
           'shortcaption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
           'caption' => { 'args' => ['keep'], 'function' => \&main::do_caption_shortcaption },
           'acronym',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
           'abbr',    {'args' => ['keep','keep'], 'function' => \&main::do_acronym_like},
);

# @image is replaced by the first arg in strings
$style_map_texi{'image'} = { 'args' => ['keep','keep','keep','keep','keep'],
       'function' => \&t2h_default_no_texi_image };

$style_map_texi{'acronym'} = { 'args' => ['keep','keep'],
       'function' => \&t2h_default_no_texi_acronym_like };
$style_map_texi{'abbr'} = { 'args' => ['keep','keep'],
       'function' => \&t2h_default_no_texi_acronym_like };

foreach my $special (keys(%special_style))
{
    $style_map{$special} = $special_style{$special}
          unless (defined($style_map{$special}));
    $style_map_pre{$special} = $special_style{$special}
          unless (defined($style_map_pre{$special}));
    $style_map_texi{$special} = { 'args' => ['keep'],
        'function' => \&t2h_remove_command }
          unless (defined($style_map_texi{$special}));
}
####### end special styles.


#foreach my $command (keys(%style_map))
#{
#    print STDERR "STYLE_MAP_TEXI $command($style_map_texi{$command}) ";
#    print STDERR "ARGS $style_map_texi{$command}->{'args'} " if (defined($style_map_texi{$command}->{'args'}));
#    print STDERR "FUN $style_map_texi{$command}->{'function'} " if (defined($style_map_texi{$command}->{'function'}));
#    print STDERR "\n";
#}

# uncomment to use the old interface
#%style_map = %old_style_map;
#%style_map_pre = %old_style_map_pre;

%simple_format_simple_map_texi = %simple_map_pre;
%simple_format_texi_map = %pre_map;
%simple_format_style_map_texi = ();

t2h_default_copy_style_map(\%style_map_texi, \%simple_format_style_map_texi);

foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
{
#    $simple_format_style_map_texi{$accent_command}->{'args'} = ['normal'];
    $simple_format_style_map_texi{$accent_command}->{'function'} = \&t2h_default_accent;
}

foreach my $hash (\%style_map, \%style_map_pre, \%style_map_texi, \%simple_format_style_map_texi)
{
  foreach my $style (keys(%{$hash}))
  {
    $hash->{$style}->{'args'} = ['normal'] if (!exists($hash->{$style}->{'args'}));
  } 
}

%default_style_map = ();
%default_style_map_pre = ();
%default_style_map_texi = ();
%default_simple_format_style_map_texi = ();

t2h_default_copy_style_map(\%style_map, \%default_style_map);
t2h_default_copy_style_map(\%style_map_pre, \%default_style_map_pre);
t2h_default_copy_style_map(\%style_map_texi, \%default_style_map_texi);
t2h_default_copy_style_map(\%simple_format_style_map_texi, \%default_simple_format_style_map_texi);

# called here because %default_style_map_texi is used.
t2h_default_set_variables_default();

#################################################################
# TeX/LaTeX styles, that can be used in math

my %default_style_tex_map;
my %default_style_latex_map;

t2h_default_copy_style_map(\%default_style_map, \%default_style_tex_map);
t2h_default_copy_style_map(\%default_style_map, \%default_style_latex_map);

# common in TeX and LaTeX and both for math and normal text

$default_style_latex_map{'w'}->{'inline_begin'} = '\mbox{';
$default_style_tex_map{'w'}->{'inline_begin'} = '\mbox{';
$default_style_latex_map{'dmn'}->{'inline_begin'} = '{\thinspace ';
$default_style_tex_map{'dmn'}->{'inline_begin'} = '{\thinspace ';

my %default_style_latex_math_map;

t2h_default_copy_style_map(\%default_style_latex_map, \%default_style_latex_math_map);

my %default_tex_latex_map = (
  'bf' => [ 'b', 'strong' ],
  'tt' => [ 'code', 'command', 'env', 'file', 'option', 'samp', 't' ],
  'it' => [ 'i', 'var', 'emph' ],
  'sf' => [ 'sanserif' ],
  'rm' => [ 'r' ],
  'sl' => [ 'dfn', 'slanted' ],
);
 
foreach my $style (keys (%default_tex_latex_map))
{
   foreach my $command (@{$default_tex_latex_map{$style}})
   {
      $default_style_tex_map{$command}->{'inline_begin'} = '{\\' . $style .' ';
      $default_style_latex_map{$command}->{'inline_begin'} = '\text' . $style .'{';
      $style = 'normal' if ($style eq 'sl');
      $default_style_latex_math_map{$command}->{'inline_begin'} = '\math' . $style .'{';
   }
}

# only in text

$default_style_latex_map{'emph'}->{'inline_begin'} = '\emph{'; 
$default_style_latex_map{'var'}->{'inline_begin'} = '\emph{'; 
$default_style_latex_map{'sc'}->{'inline_begin'} = '\textsc{'; 

foreach my $hash (\%default_style_tex_map, \%default_style_latex_map, \%default_style_latex_math_map)
{
   foreach my $command (keys(%$hash))
   {
      $hash->{$command}->{'inline_end'} = '}' if ($hash->{$command}->{'inline_begin'});
   }
}

# no kbd key sc in math
#       'kbd'                -                 ?
#       'key'                -                 ?

my %default_style_tex_math_map;

t2h_default_copy_style_map(\%default_style_tex_map, \%default_style_tex_math_map);

# We don't want to override special commands in math mode for now, as long
# as they are not handled especially. Also we don't want to modify the math
# function, it is called to close the @math command and we don't want
# it to be the turned to the default one when calling 
# FIXME maybe it would be even better not to duplicate default styles in
# math, like 'email', 'uref'....
foreach my $command (keys(%special_style), 'math')
{
   delete $default_style_tex_math_map{$command};
   delete $default_style_latex_math_map{$command};
}

foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents))
{
     $default_style_latex_map{$accent_command} = { 'function' => \&default_tex_accent };
     $default_style_tex_map{$accent_command} = { 'function' => \&default_tex_accent };
     $default_style_tex_math_map{$accent_command} = { 'function' => \&default_tex_math_accent };
     $default_style_latex_math_map{$accent_command} = { 'function' => \&default_latex_math_accent };
}

my %tex_text_accent_map = (
 ',' => 'c',
 'ringaccent' => 'r',
 'dotaccent'  => '.',
 'ubaraccent' => 'b',
 'udotaccent' => 'd',
 'ogonek'     => 'k',
 'tieaccent'  => 'tie',
);

sub default_tex_accent($$)
{
    my $text = shift;
    my $accent = shift;
    return "\\$tex_text_accent_map{$accent}\{$text\}" if ($tex_text_accent_map{$accent});
    if ($accent eq 'dotless')
    {
        return "\\$text" if ($text eq 'i' or $text eq 'j');
        return $text;
    }
    return "\\$accent\{$text\}";
}

my %tex_math_accent_map = (
 "'" => 'acute',
 '^' => 'hat',
 '`' => 'grave',
 '~' => 'tilde',
 '"' => 'ddot',
 '=' => 'bar',
 'dotaccent'  => 'dot',
 'u' => 'breve',
 'ubaraccent' => 'underline',
);

sub default_latex_math_accent($$)
{
    my $text = shift;
    my $accent = shift;
    return '\mathring{'.$text.'}' if ($accent eq 'ringaccent');
    return default_tex_math_accent($text, $accent);
}

sub default_tex_math_accent($$)
{
    my $text = shift;
    my $accent = shift;
    return "\\$tex_text_accent_map{$accent}\{$text\}" if ($tex_text_accent_map{$accent});
    if ($accent eq 'dotless')
    {
        return "\\${text}math" if ($text eq 'i' or $text eq 'j');
        return $text;
    }
    return ascii_accent($text, $accent);
}

my $kept_normal_text;

# We assume that in @math the TeX characters have already been 
# rightly protected and so don't protect once more.
sub default_tex_normal_math_text($$$$$$$;$)
{
   my @initial_args = @_;
   my $text = shift;
   my $in_raw_text = shift; # remove_texi
   my $in_preformatted = shift;
   my $in_code = shift;
   my $in_math = shift;
   my $in_simple = shift;
   my $style_stack = shift;
   my $state = shift;

   # Don't protect text in math
   if ($in_math)
   {
       $text = uc($text) if (in_cmd($style_stack, 'sc'));
       return $text;
   }
   return &kept_normal_text(@initial_args);
}

# This is the entry point to be used by users.
sub default_load_tex_math(;$)
{
   my $style = shift;
   $style = 'latex' if (!defined($style));
   %simple_map_math = %tex_default_simple_map_math;
   if ($style eq 'tex')
   {
      %math_map = %tex_default_math_things_map;
      t2h_default_copy_style_map(\%default_style_tex_math_map, \%style_map_math);
   }
   else
   {
      %math_map = %latex_default_math_things_map;
      t2h_default_copy_style_map(\%default_style_latex_math_map, \%style_map_math);
   }
   $kept_normal_text = $normal_text;
   $normal_text = \&default_tex_normal_math_text;
}

# End TeX/LaTeX styles
#################################################################

# regions expanded or not depending on the value of this hash.
# @EXPAND sets entries in this hash, and you should better use
# @EXPAND unless you know what you are doing.
%texi_formats_map = (
     'iftex' => 0, 
     'ignore' => 0, 
     'menu' => 0, 
     'ifplaintext' => 0, 
     'ifinfo' => 0,
     'ifxml' => 0,
     'ifhtml' => 0, 
     'ifdocbook' => 0, 
#     'html' => 0, 
#     'tex' => 0, 
#     'xml' => 0,
#     'docbook' => 0,
     'titlepage' => 1, 
     'documentdescription' => 1, 
     'copying' => 1, 
     'ifnothtml' => 1, 
     'ifnottex' => 1, 
     'ifnotplaintext' => 1, 
     'ifnotinfo' => 1,
     'ifnotxml' => 1,
     'ifnotdocbook' => 1, 
     'direntry' => 'normal',
     'verbatim' => 'raw', 
     'macro' => 'raw', 
     'ifclear' => 'value', 
     'ifset' => 'value' ,
     );
    
%format_map = (
#       'quotation'   =>  'blockquote',
       # lists
#       'itemize'     =>  'ul',
       'enumerate'   =>  '',
#       'multitable'  =>  'table',
       'table'       =>  '',
       'vtable'      =>  '',
       'ftable'      =>  '',
       'group'       =>  '',
       'raggedright'       =>  '',
#       'detailmenu'  =>  '',
       );

%special_list_commands = (
       'table'        =>  {},
       'vtable'       =>  {},
       'ftable'       =>  {},
#       'itemize'      =>  { 'bullet'  => '' }
       'itemize'      =>  {},
       );

%inter_item_commands = (
  'c' => 1,
  'comment' => 1,
  'cindex' => 1
);
#
# texinfo format to align attribute of paragraphs
#

%paragraph_style = (
      'center'     => 'center',
      'flushleft'  => 'left',
      'flushright' => 'right',
      );
      
# complex formats (preformatted)
%complex_format_map = ();
foreach my $complex_format ('example', 'smallexample', 'display', 
  'smalldisplay', 'lisp', 'smalllisp', 'format', 'smallformat',
  'menu', 'detailmenu', 'direntry', 'menu_comment')
{
    $complex_format_map{$complex_format} = { 'begin' => '', 'end' => '' };
}
foreach my $code_complex_format ('example', 'smallexample', 'lisp', 'smalllisp')
{
    $complex_format_map{$code_complex_format}->{'style'} = 'code';
}

# not in code_style, according to post on bug-texinfo
foreach my $format ('menu', 'detailmenu', 'direntry')
{
   $complex_format_map{$format}->{'class'} = 'menu-preformatted';
}

# not in code_style, according to post on bug-texinfo
$complex_format_map{'menu_comment'}->{'class'} = 'menu-comment';

%def_map = (
    # basic commands
    'deffn', [ 'f', 'category', 'name', 'arg' ],
    'defvr', [ 'v', 'category', 'name' ],
    'deftypefn', [ 'f', 'category', 'type', 'name', 'argtype' ],
    'deftypeop', [ 'f', 'category', 'class' , 'type', 'name', 'argtype' ],
    'deftypevr', [ 'v', 'category', 'type', 'name' ],
    'defcv', [ 'v', 'category', 'class' , 'name' ],
    'deftypecv', [ 'v', 'category', 'class' , 'type', 'name' ],
    'defop', [ 'f', 'category', 'class' , 'name', 'arg' ],
    'deftp', [ 't', 'category', 'name', 'argtype' ],
    # shortcuts
    # FIXME i18n
    'defun', 'deffn Function',
    'defmac', 'deffn Macro',
    'defspec', 'deffn {Special Form}',
    'defvar', 'defvr Variable',
    'defopt', 'defvr {User Option}',
    'deftypefun', 'deftypefn {Function}',
    'deftypevar', 'deftypevr Variable',
    'defivar', 'defcv {Instance Variable}',
    'deftypeivar', 'deftypecv {Instance Variable}',
    'defmethod', 'defop Method',
    'deftypemethod', 'deftypeop Method',
         );

$def_always_delimiters = "()[]";
$def_in_type_delimiters = ",;";
$def_argument_separator_delimiters = "()[],";

$warn_var_character_quoted = quotemeta("()[],");

# basic x commands
foreach my $key (keys(%def_map))
{
    $def_map{$key . 'x'} = $def_map{$key};
}

#
# miscalleneous commands
#
# Depending on the value, the command arg or spaces following the command
#     are handled differently:
# 
# the value is a reference on a hash.
# the hash keys are
#    'arg'  if the value is 'line' then the remaining of the line is the arg
#           if it is a number it is the number of args (separated by spaces)
#    'skip' if the value is 'line' then the remaining of the line is skipped
#           if the value is 'space' space but no newline is skipped
#           if the value is 'whitespace' space is skipped
#           if the value is 'linewhitespace' space is skipped if there are 
#                 only spaces remaining on the line
#           if the value is 'linespace' space but no newline is skipped if 
#                 there are only spaces remaining on the line
#    'keep' if true the args and the macro are kept, otherwise the macro 
#          args and skipped stuffs are removed
%misc_command = (
        'bye' => {'skip' => 'line'}, # no arg
        # set, clear
        #'set' => {'skip' => 'line'}, # special arg
        'set' => {'arg' => 'line'}, # special arg
        #'clear' => {'skip' => 'line'}, # special arg
        'clear' => {'arg' => 1, 'skip' => 'line'}, # special arg
        'alias' => {'args' => 3, 'skip' => 'line'}, # special arg
        # comments
        'comment' => {'arg' => 'line'},
        'c' => {'arg' => 'line'},

        # not needed for formatting
        'raisesections' => {'skip' => 'line'},  # no arg
        'lowersections' => {'skip' => 'line'}, # no arg
        'contents' => {}, # no arg
        'shortcontents' => {}, # no arg
        'summarycontents'=> {}, # no arg
        'setcontentsaftertitlepage' => {}, # no arg
        'setshortcontentsaftertitlepage' => {}, # no arg
        #'clickstyle' => {'skip' => 'line'}, # arg should be an @-command
        'clickstyle' => {'arg' => 'line'}, # arg should be an @-command
        # in preamble
        'novalidate' => {}, # no arg
        'dircategory'=> {'arg' => 'line'}, # line. Position with regard 
                         # with direntry is significant
        'pagesizes' => {'skip' => 'line', 'arg' => 'line'}, # can have 2 args 
                                 # or one? 200mm,150mm 11.5in
        'finalout' => {'skip' => 'line'}, # no arg
        'paragraphindent' => {'skip' => 'line', 'arg' => 1}, # arg none asis 
                             # or a number and forbids anything else on the line
        'firstparagraphindent' => {'skip' => 'line', 'arg' => 1}, # none insert
        'frenchspacing' => {'arg' => 1, 'skip' => 'line'}, # on off
                                       # not so sure about 'skip' => 'line'
        'fonttextsize' => {'arg' => 1}, # 10 11
        'allowcodebreaks' => {'arg' => 1, 'skip' => 'line'}, # false or true
        'exampleindent' => {'skip' => 'line', 'arg' => 1}, # asis or a number
        'footnotestyle'=> {'skip' => 'line', 'arg' => 1}, # end and separate
                                 # and nothing else on the line
        'afourpaper' => {'skip' => 'line'}, # no arg
        'afivepaper' => {'skip' => 'line'}, # no arg
        'afourlatex' => {'skip' => 'line'}, # no arg
        'afourwide' => {'skip' => 'line'}, # no arg
        'headings'=> {'skip' => 'line', 'arg' => 1}, 
                    #off on single double singleafter doubleafter
                    # interacts with setchapternewpage
        'setchapternewpage' => {'skip' => 'line', 'arg' => 1}, # off on odd
        'everyheading' => {'arg' => 'line'},
        'everyfooting' => {'arg' => 'line'},
        'evenheading' => {'arg' => 'line'},
        'evenfooting' => {'arg' => 'line'},
        'oddheading' => {'arg' => 'line'},
        'oddfooting' => {'arg' => 'line'},
        'smallbook' => {'skip' => 'line'}, # no arg
        'setfilename' => {'arg' => 'line'},
        'definfoenclose' => {'arg' => 'line'},
        #'shorttitle' => {'arg' => 'line', 'texi' => 1},
        #'shorttitlepage' => {'arg' => 'line', 'texi' => 1},
        #'settitle' => {'arg' => 'line', 'texi' => 1},
        #'author' => {'arg' => 'line', 'texi' => 1},
        #'subtitle' => {'arg' => 'line', 'texi' => 1},
        #'title' => {'arg' => 'line', 'texi' => 1},
        'shorttitle' => {'arg' => 'line'},
        'shorttitlepage' => {'arg' => 'line'},
        'settitle' => {'arg' => 'line'},
        'author' => {'arg' => 'line'},
        'subtitle' => {'arg' => 'line'},
        'title' => {'arg' => 'line'},
        'syncodeindex' => {'skip' => 'line', 'arg' => 2}, 
                          # args are index identifiers
        'synindex' => {'skip' => 'line', 'arg' => 2},
        'defindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
        'defcodeindex' => {'skip' => 'line', 'arg' => 1}, # one identifier arg
        #'documentlanguage' => {'skip' => 'whitespace', 'arg' => 1}, 
        'documentlanguage' => {'skip' => 'line', 'arg' => 1}, 
                                                       # language code arg
        'kbdinputstyle' => {'skip' => 'whitespace', 'arg' => 1}, # code 
                                                        #example distinct
        'everyheadingmarks' => {'skip' => 'line', 'arg' => 1}, # top bottom
        'everyfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
        'evenheadingmarks' => {'skip' => 'whitespace', 'arg' => 1},
        'oddheadingmarks' => {'skip' => 'whitespace', 'arg' => 1},
        'evenfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
        'oddfootingmarks' => {'skip' => 'whitespace', 'arg' => 1},
        'sp' => {'skip' => 'line', 'arg' => 1}, # no arg 
                                    # at the end of line or a numerical arg
        # formatting
        'page' => {}, # no arg (pagebreak)
        'refill' => {}, # no arg (obsolete, to be ignored)
        'noindent' => {'skip' => 'whitespace'}, # no arg
        'indent' => {'skip' => 'whitespace'},
        'need' => {'skip' => 'line', 'arg' => 1}, # one numerical/real arg
        'exdent' => {'skip' => 'space'},  
        # not valid for info (should be in @iftex)
        'vskip' => {'arg' => 'line'}, # arg line in TeX
        'cropmarks' => {}, # no arg
        # miscalleneous
        'verbatiminclude'=> {'arg' => 'line'},
        'documentencoding' => {'arg' => 1, 'skip' => 'line'}, 
        # obsolete @-commands. Remove spaces and end of lines after the 
        # commands? If no, they can lead to empty lines
        'quote-arg' => {'skip' => 'line'},
        'allow-recursion' => {'skip' => 'line'},
     );

my %misc_command_old = (
        # not needed for formatting
        'raisesections', 'line',  # no arg
        'lowersections', 'line', # no arg
        'contents', 1, # no arg
        'shortcontents', 1, # no arg
        'summarycontents', 1, # no arg
        'detailmenu', 'whitespace', # no arg
        'end detailmenu', 'whitespace', # no arg
        #'end detailmenu', 1, # no arg
        'novalidate', 1, # no arg
        'bye', 'line', # no arg
        # comments
        'comment', 'line',
        'c', 'line',
        # in preamble
        'dircategory', 'line', # line. Position with regard with direntry is 
                               # significant
        'pagesizes', 'line arg2', # can have 2 args 
        'finalout', 1, # no arg
        'paragraphindent', 'line arg1', # in fact accepts only none asis 
                             # or a number and forbids anything else on the line
        'firstparagraphindent', 'line arg1', # in fact accepts only none insert
        'exampleindent', 'line arg1', # in fact accepts only asis or a number
        'footnotestyle', 'line arg1', # in fact accepts only end and separate
                                 # and nothing else on the line
        'afourpaper', 'line', # no arg
        'afourlatex', 'line', # no arg
        'afourwide', 'line',  # no arg
        'headings', 'line', # one arg, possibilities are 
                    #off on single double singleafter doubleafter
                    # interacts with setchapternewpage
        'setchapternewpage', 'line', # no arg
        'everyheading', 'line',
        'everyfooting', 'line',
        'evenheading', 'line',
        'evenfooting', 'line',
        'oddheading', 'line',
        'oddfooting', 'line',
        'smallbook', 'line', # no arg
        'setfilename', 'line',
        'shorttitle', 'linetexi',
        'shorttitlepage', 'linetexi',
        'settitle', 'linetexi',
        'author', 'linetexi',
        'subtitle', 'linetexi',
        'title','linetexi',
        'syncodeindex','linespace arg2', # args are 
        'synindex','linespace arg2',
        'defindex', 'line arg1', # one identifier arg
        'defcodeindex', 'line arg1', # one identifier arg
        'documentlanguage', 'whitespace arg1', # one language code arg
        'kbdinputstyle', 'whitespace arg1', # one arg within 
                                 #code example distnct
        'sp', 'whitespace arg1', # no arg at the en of line or a numerical arg
        # formatting
        'page', 1, # no arg (pagebreak)
        'refill', 1, # no arg (obsolete, to be ignored))
        'noindent', 'space', # no arg
        'need', 'line arg1', # one numerical/real arg
        'exdent', 'space',  
        # not valid for info (should be in @iftex)
        'vskip', 'line', # arg line in TeX
        'cropmarks', 1, # no arg
        # miscalleneous
        'verbatiminclude', 'line',
        'documentencoding', 'arg1',
     );

# The command_handler arrays are for commands formatted externally.
# The function references in @command_handler_init are called
# before the second pass, before the @-commands text collection.
# Those in @command_handler_process are called between the second pass
# and the third pass, after collection of @-commands text and before their
# expansion.
# Those in @command_handler_process are called after the third pass,
# after the document generation.
@command_handler_setup = ();
@command_handler_init = ();
@command_handler_names = ();
@command_handler_process = ();
@command_handler_output = ();
@command_handler_finish = ();


sub t2h_default_push_handler($$)
{
   my $function = shift;
   my $handlers = shift;
   push @$handlers, $function unless (grep {$_ eq $function} @$handlers);
}

# the keys of %command_handler are @-command names and the value
# is a hash reference with the following keys:
# 'init'          function reference used to collect the @-command text
# 'expand'        function reference used when expanding the @-command text
%command_handler = ();


# formatting functions

$anchor            = \&t2h_default_anchor;
$def_item          = \&t2h_default_def_item;
$def               = \&t2h_default_def;
$menu_command      = \&t2h_default_menu_command;
$menu_link         = \&t2h_default_menu_link;
#$menu_comment      = \&t2h_default_menu_comment;
$menu_description  = \&t2h_default_menu_description;
#$simple_menu_link  = \&t2h_default_simple_menu_link;
$table_item        = \&t2h_default_table_item;
$table_line        = \&t2h_default_table_line;
$table_list        = \&t2h_default_table_list;
$row               = \&t2h_default_row;
$cell              = \&t2h_default_cell;
$list_item         = \&t2h_default_list_item;
$comment           = \&t2h_default_comment;
$def_line          = \&t2h_default_def_line;
$def_line_no_texi  = \&t2h_default_def_line_no_texi;
$raw               = \&t2h_default_raw;
$raw_no_texi       = \&t2h_default_raw_no_texi;
$heading           = \&t2h_default_heading;
$heading_text      = \&t2h_default_heading_text;
$heading_text_preformatted      = \&t2h_default_heading_text_preformatted;
$element_heading   = \&t2h_default_element_heading;
$heading_no_texi   = \&t2h_default_heading_no_texi;
$external_href     = \&t2h_default_external_href;
$paragraph         = \&t2h_default_paragraph;
$preformatted      = \&t2h_default_preformatted;
$foot_line_and_ref = \&t2h_default_foot_line_and_ref;
$foot_section      = \&t2h_default_foot_section;
$image_files       = \&t2h_default_image_files;
$image             = \&t2h_default_image;
$index_entry_label = \&t2h_default_index_entry_label;
$index_summary     = \&t2h_default_index_summary;
$summary_letter    = \&t2h_default_summary_letter;
$index_entry       = \&t2h_default_index_entry;
$index_entry_command = \&t2h_default_index_entry_command;
$index_letter      = \&t2h_default_index_letter;
#$printindex       = \&t2h_default_printindex;
$print_index       = \&t2h_default_print_index;
$protect_text      = \&t2h_default_protect_text;
$normal_text       = \&t2h_default_normal_text;
$cartouche         = \&t2h_default_cartouche;
$sp                = \&t2h_default_sp;
$definition_category      = \&t2h_default_definition_category;
$definition_index_entry   = \&t2h_default_definition_index_entry;
$copying_comment          = \&t2h_default_copying_comment;
$documentdescription      = \&t2h_default_documentdescription;
$index_summary_file_entry = \&t2h_default_index_summary_file_entry;
$index_summary_file_end   = \&t2h_default_index_summary_file_end;
$index_summary_file_begin = \&t2h_default_index_summary_file_begin;
$empty_line               = \&t2h_default_empty_line;
$float                     = \&t2h_default_float;
$listoffloats             = \&t2h_default_listoffloats;
$listoffloats_entry       = \&t2h_default_listoffloats_entry;
$listoffloats_caption     = \&t2h_default_listoffloats_caption;
$listoffloats_float_style = \&t2h_default_listoffloats_float_style;
$listoffloats_style       = \&t2h_default_listoffloats_style;
$acronym_like             = \&t2h_default_acronym_like;
$quotation                = \&t2h_default_quotation;
$paragraph_style_command  = \&t2h_default_paragraph_style_command;
$heading_texi             = \&t2h_default_heading_texi;
$index_element_heading_texi = \&t2h_default_index_element_heading_texi;
$element_label              = \&t2h_default_element_label;
$anchor_label               = \&t2h_default_anchor_label;
$preserve_misc_command      = \&t2h_default_preserve_misc_command;
$format_list_item_texi      = \&t2h_default_format_list_item_texi;
$begin_format_texi          = \&t2h_default_begin_format_texi;
$insertcopying              = \&t2h_default_insertcopying;
$simple_command             = \&t2h_default_simple_command;
$thing_command              = \&t2h_default_thing_command;
$line_command               = \&t2h_default_line_command;
$internal_links             = \&t2h_default_internal_links;

# address is not used anymore
$address           = \&t2h_default_address;

# return the line after preserving things according to misc_command map.
# You should not change it. It is here, nevertheless, to be used
# in other function references if needed.
sub t2h_default_preserve_misc_command($$)
{
    my $line = shift;
    my $macro = shift;
    my $text = '';
    my $args = [];
    my $skip_spec = '';
    my $arg_spec = '';

#print STDERR "HHHHHHHHH $line $macro\n";
    $skip_spec = $misc_command{$macro}->{'skip'}
        if (defined($misc_command{$macro}->{'skip'}));
    $arg_spec = $misc_command{$macro}->{'arg'}
        if (defined($misc_command{$macro}->{'arg'}));

    if ($arg_spec eq 'line')
    {
        $text .= $line;
        $args = [ $line ];
        $line = '';
    }
    elsif ($arg_spec)
    {
        my $arg_nr = $misc_command{$macro}->{'arg'};
        while ($arg_nr)
        {
            if ($line =~ s/^(\s+)(\S*)//o)
            {
                $text .= $1.$2;
                my $argument = $2;
                push @$args, $argument if ($argument ne '');
            }
            else
            {
                last;
            }
            $arg_nr--;
        }
#        while ($arg_nr)
#        {
#            $line =~ s/(\s+\S*)//o;
#            my $argument = $1;
#            if (defined($argument))
#            {
#                $text .= $argument;
#                push @$args, $argument;
#            }
#            $arg_nr--;
#        }
    }
   
    if ($macro eq 'bye')
    {
        $line = '';
        $text = "\n";
    }
    elsif ($skip_spec eq 'linespace')
    {
        if ($line =~ /^\s*$/o)
        {
            $line =~ s/^([ \t]*)//o;
            $text .= $1;
        }
    }
    elsif ($skip_spec eq 'linewhitespace')
    {
        if ($line =~ /^\s*$/o)
        {
            $text .= $line;
            $line = '';
        }	
    }
    elsif ($skip_spec eq 'line')
    {
        $text .= $line;
        $line = '';
    }
    elsif ($skip_spec eq 'whitespace')
    {
        $line =~ s/^(\s*)//o;
        $text .=  $1;
    }
    elsif ($skip_spec eq 'space')
    {
        $line =~ s/^([ \t]*)//o;
        $text .= $1;
    }
    $line = '' if (!defined($line));
    return ($line, $text, $args);
}

sub t2h_default_simple_command($$$$$)
{
    my $command = shift;
    my $in_preformatted = shift;
    my $in_math = shift;
    my $line_nr = shift;
    my $state = shift;

    if ($in_math)
    {
        my $result = $simple_map_pre{$command};
        $result = $simple_map_math{$command} if (defined($simple_map_math{$command}));
        return $result;
    }
    elsif ($in_preformatted)
    {
        return $simple_map_pre{$command};
    }
    else
    {
        return $simple_map{$command};
    }
}

sub t2h_default_thing_command($$$$$$)
{
    my $command = shift;
    my $text = shift;
    my $in_preformatted = shift;
    my $in_math = shift;
    my $line_nr = shift;
    my $state = shift;

    my $result;
    if ($in_math)
    {
        $result = $pre_map{$command};
        $result = $math_map{$command} if (defined($math_map{$command}));
    }
    elsif ($in_preformatted)
    {
        $result = $pre_map{$command};
    }
    else 
    {
        $result = $things_map{$command};
    }
    return $result . $text;
}

# this is called each time a format begins. Here it is used to keep a
# record of the multitables to have a faithful count of the cell nr.
sub t2h_default_begin_format_texi($$$)
{
    my $command = shift;
    my $line = shift;
    my $state = shift;

   # remove space in front of center, unless it removes the end of line!
    $line =~ s/^\s*// if ($command eq 'center' and $line =~ /\S/);
    return $line;
}

# This function is called whenever a complex format is processed
#
# arguments:
# name of the format
# text appearing inside the format
#
# an eval of $complex_format->{format name}->{'begin'} should lead to the
# beginning of the complex format, an eval of 
# $complex_format->{format name}->{'end'}  should lead to the end of the 
# complex format.
sub t2h_default_complex_format($$)
{
    my $name = shift;
    my $text = shift;
    return '' if ($text eq '');
    return '' if ($name eq 'direntry');
    my $beginning;
    my $end;
    # FIXME obsoleted in nov 2009
    if (exists($complex_format_map->{$name}))
    {
        $beginning = eval "$complex_format_map->{$name}->{'begin'}";
        if ($@ ne '')
        {
            main::msg_debug("Evaluation of $complex_format_map->{$name}->{'begin'}: $@");
            $beginning = '';

        }
        $end = eval "$complex_format_map->{$name}->{'end'}";
        if ($@ ne '')
        {
            main::msg_debug("Evaluation of $complex_format_map->{$name}->{'end'}: $@");
            $end = '';
        }
    }
    else
    {
        $beginning = $complex_format_map{$name}->{'begin'};
        $beginning = '' if (!defined($beginning));
        $end = $complex_format_map{$name}->{'end'};
        $end = '' if (!defined($end));
    }
    return $beginning . $text . $end;	
}

sub t2h_default_empty_line($$)
{
    my $text = shift;
    my $state = shift;
    #ignore the line if it just follows a deff
    return '' if ($state->{'deff_line'});
    return $text;
}

sub t2h_default_unknown($$$$$)
{
    my $macro = shift;
    my $line = shift;
    my $pass = shift;
    my $stack = shift;
    my $state = shift;
    
    my ($result_line, $result, $result_text, $message);
    return ($line, 0, undef, undef);
}

sub t2h_default_unknown_style($$$$$)
{
    my $command = shift;
    my $text = shift;
    my $state = shift;
    my $no_close = shift;
    my $no_open = shift;
    
    my ($result, $result_text, $message);
    return (0, undef, undef);
}

sub t2h_default_caption_shortcaption($)
{
    my $float = shift;
    my $caption_lines;
    my $shortcaption_lines;
    my $style = $float->{'style_texi'};
    if (defined($float->{'nr'}))
    {
        my $nr = $float->{'nr'};
        if ($style ne '')
        {
            $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr});
        }
        else 
        {
            $style = $nr;
        }
    }
    my $empty_caption = 1;
    if (defined($float->{'caption_texi'}) and @{$float->{'caption_texi'}})
    {
        @$caption_lines = @{$float->{'caption_texi'}};
        $caption_lines->[0] =~ s/^\s*//;
        if ($caption_lines->[0] =~ /\S/ or @$caption_lines > 2)
        {
            $empty_caption = 0;
        }
    }
    
    if (!$empty_caption)
    {
        if (defined($style))
        {
            $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {caption_first_line}', { 'style' => $style, 'caption_first_line' => $caption_lines->[0] });
        }
        else
        {
            $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' .  $caption_lines->[0];
        }
        push @$caption_lines, "}\n";
    }
    elsif (defined($style))
    {
        $caption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n";
    }

    my $empty_shortcaption = 1;
    if (defined($float->{'shortcaption_texi'}) and @{$float->{'shortcaption_texi'}})
    {
        @$shortcaption_lines = @{$float->{'shortcaption_texi'}};
        $shortcaption_lines->[0] =~ s/^\s*//;
        if ($shortcaption_lines->[0] =~ /\S/ or @$shortcaption_lines > 1)
        {
            $empty_shortcaption = 0;
        }
    }
    
    if (!$empty_shortcaption)
    {
         if (defined($style))
         {
              $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . gdt('{style}: {shortcaption_first_line}', { 'style' => $style, 'shortcaption_first_line' => $shortcaption_lines->[0] });
         }
         else
         {
              $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' .  $shortcaption_lines->[0];
         }
         push @$shortcaption_lines, "}\n";
    }
    elsif (defined($style))
    {
         $shortcaption_lines->[0] = '@'.$CAPTION_STYLE.'{' . $style . '}' . "\n";
    }
    return ($caption_lines, $shortcaption_lines);
}

# everything is done in &$float
sub t2h_default_caption_shortcaption_command($$$$)
{
   my $command = shift;
   my $text = shift;
   my $texi_lines = shift;
   my $float_element = shift;
   return '';
}

sub t2h_default_float($$$$$)
{
    my $text = shift;
    my $float = shift;
    my $caption = shift;
    my $shortcaption = shift;
    
    my $label = '';
    if (exists($float->{'id'}))
    {
        $label = &$anchor($float->{'id'});
    }
    my $caption_text = '';
    
    if (defined($float->{'caption_texi'}))
    {
        $caption_text = $caption;
    }
    elsif (defined($float->{'shortcaption_texi'}))
    {
        $caption_text = $shortcaption;
    }
    elsif (defined($caption))
    {
        $caption_text = $caption;
    }
    
    return $text . "\n" . $caption_text;
}

sub t2h_default_listoffloats_style($)
{
    my $style_texi = shift;
    return ($style_texi);
}

sub t2h_default_listoffloats_float_style($$)
{
    my $style_texi = shift;
    my $float = shift;
    
    my $style = $float->{'style_texi'};
    #print STDERR "listoffloat/float style mismatch $style_texi $style\n" if ($style_texi ne $style);
    if (defined($float->{'nr'}))
    {
         my $nr = $float->{'nr'};
         if ($style ne '')
         {
              $style = gdt('{style} {number}', { 'style' => $style, 'number' => $nr});
         }
         else 
         {
              $style = $nr;
         }
    }
    return $style;
}

sub t2h_default_listoffloats_caption($)
{
    my $float = shift;
    if (defined($float->{'shortcaption_texi'}))
    {
         return ([ @{$float->{'shortcaption_texi'}} ], 'shortcaption');
    }
    elsif (defined($float->{'caption_texi'}))
    {
         return ([ @{$float->{'caption_texi'}} ], 'caption');
    }
    return ([ ], undef);
}

sub t2h_default_listoffloats_entry($$$$)
{
    my $style_texi = shift;
    my $float = shift;
    my $float_style = shift;
    my $caption = shift;
    my $href = shift;

    my @lines = split /^/, $caption;
    $caption = $lines[0];
    $caption = '' if (!defined($caption));
    chomp ($caption);

    $caption = $float->{'text'} if ($caption eq '' and defined($float->{'text'}) and $float->{'text'} =~ /\S/);
    
    return  "* $float_style: ${caption}\n";
}

sub t2h_default_listoffloats($$$)
{
    my $style_texi = shift;
    my $style = shift;
    my $float_entries = shift;

    my $result = "* List of $style:\n";
    foreach my $float_entry (@$float_entries)
    {
         $result .= $float_entry;
    }
    return $result . "\n";
} 

sub t2h_default_insertcopying($$$)
{
    my $text = shift;
    my $comment = shift;
    my $simple_text = shift;
    return $text;
}

sub t2h_default_protect_text($)
{
   my $text = shift;
   return $text;
}

# This function is used to protect characters which are special in xml
# in inline text:  &, ", <, and >. 
#
# argument:
# text to be protected
sub xml_default_protect_text($)
{
   my $text = shift;
   $text =~ s/&/&amp;/g;
   $text =~ s/</&lt;/g;
   $text =~ s/>/&gt;/g;
   $text =~ s/\"/&quot;/g;
   return $text;
}

sub in_cmd($$)
{
   my $style_stack = shift;
   my $command = shift;
   my $result = 0;
   if ($style_stack and scalar(@{$style_stack}))
   {
       my $level = $#$style_stack;
       #print STDERR ":::$level ::@{$style_stack}\n";
       while ($level >= 0)
       {
           if ($style_stack->[$level] eq $command)
           {
               $result = 1;
               last;
           }
           $level--;
       }
   } 
   return $result;
}
#
#

sub in_small_caps($)
{
   my $style_stack = shift;
   my $in_sc = 0;
   if ($style_stack and scalar(@{$style_stack}))
   {
       my $level = $#$style_stack;
       #print STDERR ":::$level ::@{$style_stack}\n";
       while ($level >= 0)
       {
           if ($style_stack->[$level] eq 'sc')
           {
               $in_sc = 1;
               last;
           }
           $level--;
       }
   } 
   return $in_sc;
}
#
#
sub t2h_default_normal_text($$$$$$$;$)
{
   my @initial_args = @_;
   my $text = shift;
   my $in_raw_text = shift; # remove_texi
   my $in_preformatted = shift;
   my $in_code = shift;
   my $in_math = shift;
   my $in_simple = shift;
   my $style_stack = shift;
   my $state = shift;

  # like utf8.pm
   if (get_conf('ENABLE_ENCODING') and !get_conf('ENABLE_ENCODING_USE_ENTITY') and defined(get_conf('ENCODING_NAME')) and get_conf('ENCODING_NAME') eq 'utf-8' and get_conf('USE_UNICODE'))
   {
      return &t2h_utf8_normal_text(@initial_args);
   }

   $text = uc($text) if (in_cmd($style_stack, 'sc'));
   if (! $in_code and !$in_preformatted)
   {
         $text =~ s/---/\x{1F}/g;
         $text =~ s/--/-/g;
         $text =~ s/\x{1F}/--/g;
         $text =~ s/``/"/g;
         $text =~ s/\'\'/"/g;
   }
   else
   {
       # to be like tex. This would be wrong, however.
#       my $special_code = 0;
#       $special_code = 1 if (in_cmd($style_stack, 'code') or 
#           in_cmd($style_stack, 'example') or in_cmd($style_stack, 'verbatim'));
#       $text =~ s/'/\&rsquo\;/g unless ($special_code and exists($main::value{'txicodequoteundirected'}));
#       $text =~ s/`/\&lsquo\;/g unless ($special_code and exists($main::value{'txicodequotebacktick'}));
   }
   $text = t2h_text_substitutions($text, $in_raw_text, ($in_preformatted or $in_code), $in_simple);
   return $text;
}

sub t2h_default_url_and_text($;$)
{
    my $url = shift;
    my $text = shift;
    if (!defined($text) or $text eq '')
    {
       return "<$url>" if (defined($url) and $url ne '');
       return '';
    }
    else
    {
        return $text if (!defined($url) or $url eq '');
        return "$text <$url>";
    }
}

# This function produces an anchor. This need is quite html specific.
#
# arguments:
# $name           :   anchor name
# $href           :   anchor href
# text            :   text displayed
# extra_attribs   :   added to anchor attributes list
sub t2h_default_anchor($;$$$)
{
    my $name = shift;
    my $href = shift;
    my $text = shift;
    my $attributes = shift;
    return $text if (defined($text));
    return '';
}

# This function is used to format the text associated with a @deff/@end deff
#
# argument:
# text
#
# DEF_TABLE should be used to distinguish between @def formatted as table
# and as definition lists.
sub t2h_default_def_item($$$)
{
    my $text = shift;
    my $only_inter_item_commands = shift;
    my $command = shift;
    if ($text =~ /\S/)
    {
        return $text;
    }
    return '';
}

sub t2h_default_definition_category($$$$)
{
    my $name = shift;
    my $class = shift;
    my $style = shift;
    my $command = shift;
    return ($name) if (!defined($class) or $class =~ /^\s*$/);
    if ($style eq 'f')
    {
        return gdt('{name} on {class}', { 'name' => $name, 'class' => $class });
    }
    elsif ($style eq 'v')
    {
        return gdt('{name} of {class}', { 'name' => $name, 'class' => $class });
    }
    else
    {
        return $name;
    }
}

sub t2h_default_definition_index_entry($$$$)
{
    my $name = shift;
    my $class = shift;
    my $style = shift;
    my $command = shift;
    return ($name) if (!defined($class) or $class =~ /^\s*$/);
    if ($style eq 'f')
    {
        return gdt('{name} on {class}', { 'name' => $name, 'class' => $class });
    }
    elsif ($style eq 'v' and $command ne 'defcv')
    {
        return gdt('{name} of {class}', { 'name' => $name, 'class' => $class });
    }
    else
    {
        return $name;
    }
}

sub t2h_default_summary_letter($$$$$$$)
{
   my $letter = shift;
   my $file = shift;
   my $default_identifier = shift;
   my $index_element_id = shift;
   my $number = shift;
   my $index_element = shift;
   my $index_name = shift;

   return '';
}


# format the container for the @deffn line and text
# 
# argument
# text of the whole @def, line and associated text.
#
# DEF_TABLE should be used.
sub t2h_default_def($$)
{
    my $text = shift;
    my $command = shift;
    if ($text =~ /\S/)
    {
        return $text;
    }
    return '';

}

# a whole menu
#
# argument:
# the whole menu text (entries and menu comments)
#
# argument:
# whole menu text.
# not used since menu is a normal preformatted command with SIMPLE_MENU
sub t2h_default_menu_command($$$)
{
    my $format = shift;
    my $text = shift;
    my $in_preformatted = shift;
    return "* Menu:\n".$text."\n";

}

# formats a menu entry link pointing to a node or section 
#
# arguments:
# the entry text
# the state, a hash reference holding informations about the context, with a 
#     usefull entry, 'preformatted', true if we are in a preformatted format
#     (a format keeping space between words). In that case a function
#     of the main program, main::do_preformatted($text, $state) might 
#     be used to format the text with the current format style.
# href is optionnal. It is the reference to the section or the node anchor
#     which should be used to make the link (typically it is the argument 
#     of a href= attribute in a <a> element).
sub t2h_default_menu_link($$$$$$$$)
{
    my $entry = shift;
    my $state = shift;
    my $href = shift;
    my $node = shift;
    my $title = shift;
    my $ending = shift;
    my $has_title = shift;
    my $command_stack = shift;
    my $preformatted = shift;

    $title = '' unless ($has_title);
    $title .= ':' if ($title ne '');
    return "$MENU_SYMBOL$title$node$ending" if (get_conf('NODE_NAME_IN_MENU'));
    return "$MENU_SYMBOL$title$entry$ending";
}

# formats a menu entry description, ie the text appearing after the node
# specification in a menu entry an spanning until there is another
# menu entry, an empty line or some text at the very beginning of the line
# (we consider that text at the beginning of the line begins a menu comment) 
#
# arguments:
# the description text
# the state. See menu_entry.
# the heading of the element associated with the node.
# not usd since in SIMPLE_MENU
sub t2h_default_menu_description($$$$)
{
    my $text = shift;
    my $state = shift;
    my $element_text = shift;
    my $command_stack = shift;
    my $preformatted = shift;

    return $text;
}

%htmlxref_entries = (
 'node' => [ 'node', 'section', 'chapter', 'mono' ],
 'section' => [ 'section', 'chapter','node', 'mono' ],
 'chapter' => [ 'chapter', 'section', 'node', 'mono' ],
 'mono' => [ 'mono', 'chapter', 'section', 'node' ],
);


# Construct a href to an external source of information.
# node is the node with texinfo @-commands
# node_id is the node transliterated and transformed as explained in the
#         texinfo manual
# node_xhtml_id is the node transformed such that it is unique and can 
#     be used to make an html cross ref as explained in the texinfo manual
# file is the file in '(file)node'
# This is used to construct href, so is likely to be ignored oustside of
# html.
sub t2h_default_external_href($$$)
{
    my $node = shift;
    my $node_id = shift;
    my $node_xhtml_id = shift;
    my $file = shift;
    $file = '' if (!defined($file));
    my $default_target_split = get_conf('EXTERNAL_CROSSREF_SPLIT');
    my $target_split;
    #my $target_mono;
    #my $href_split;
    #my $href_mono;
    if ($file ne '')
    {
         if (get_conf('NEW_CROSSREF_STYLE'))
         {
             $file =~ s/\.[^\.]*$//;
             $file =~ s/^.*\///;
             my $href;
             my $document_split = get_conf('SPLIT');
             $document_split = 'mono' if (!$document_split);
             my $split_found;
             if (exists($Texi2HTML::THISDOC{'htmlxref'}->{$file}))
             {
                  foreach my $split_ordered (@{$htmlxref_entries{$document_split}})
                  {
                       if (defined($Texi2HTML::THISDOC{'htmlxref'}->{$file}->{$split_ordered}))
                       {
                            $split_found = $split_ordered;
                            $href = $Texi2HTML::THISDOC{'htmlxref'}->{$file}->{$split_ordered};
                            last;
                       }
                  }
             }
             if (defined($split_found))
             {
                  $target_split = 1 unless ($split_found eq 'mono');
             }
             else
             { # nothing specified for that manual, use default
                  $target_split = $default_target_split;
             }

             if ($target_split)
             {
                  if (defined($href))
                  {
                       $file = $href;
                  }
                  elsif (defined(get_conf('EXTERNAL_DIR')))
                  {
                       $file = get_conf('EXTERNAL_DIR')."/$file";
                  }
                  elsif (get_conf('SPLIT'))
                  {
                       $file = "../$file";
                  }
                  $file .= "/";
             }
             else
             {# target not split
                  if (defined($href))
                  {
                       $file = $href;
                  }
                  else
                  {
                       if (defined(get_conf('EXTERNAL_DIR')))
                       {
                            $file = get_conf('EXTERNAL_DIR')."/$file";
                       }
                       elsif (get_conf('SPLIT'))
                       {
                           $file = "../$file";
                       }
                       $file .= "." . get_conf('NODE_FILE_EXTENSION');
                  }
             }
         }
         else
         {
             $file .= "/";
             if (defined(get_conf('EXTERNAL_DIR')))
             {
                 $file = get_conf('EXTERNAL_DIR') . $file;
             }
             else
             {
                 $file = '../' . $file;
             } 
         }
    }
    else
    {
        $target_split = $default_target_split;
    }
    if ($node eq '')
    {
         if (get_conf('NEW_CROSSREF_STYLE'))
         {
             if ($target_split)
             {
                 if (defined(get_conf('TOP_NODE_FILE_TARGET')))
                 {
                     return $file . get_conf('TOP_NODE_FILE_TARGET') . '.' . get_conf('NODE_FILE_EXTENSION') . '#Top';
                 }
                 else
                 {
                     return $file . '#Top';
                 }
             }
             else
             {
                  return $file . '#Top';
             }
         }
         else
         {
             return $file;
         }
    }
    my $target;
    if (get_conf('NEW_CROSSREF_STYLE'))
    {
         $node = $node_id;
         $target = $node_xhtml_id;
    }
    else
    {
         $node = main::remove_texi($node);
         $node =~ s/[^\w\.\-]/-/g;
    }
    my $file_basename = $node;
    $file_basename = get_conf('TOP_NODE_FILE_TARGET') if ($node =~ /^top$/i and defined(get_conf('TOP_NODE_FILE_TARGET')));
    if (get_conf('NEW_CROSSREF_STYLE'))
    {
        if ($target_split)
        {
            return $file . $file_basename . '.'.get_conf('NODE_FILE_EXTENSION') . '#' . $target;
        }
        else
        {
            return $file . '#' . $target;
        }
    }
    else
    {
        return $file . $file_basename . '.'.get_conf('NODE_FILE_EXTENSION');
    }
}

# format a reference external to the generated manual. This produces a full 
# reference with introductive words and the reference itself.
#
# arguments:
# type of the reference: xref (reference at the beginning of a sentence),
#     pxref (reference in a parenthesis),  
# section in the book. This might be undef.
# book name.
# manual file name
# href linking to the html page containing the referenced node. A typical
#     use for this href is a href attribute in an <a> element
# cross reference name
# array of texi arguments of the reference
# array of the formatted arguments of the reference
# node name
sub t2h_default_external_ref($$$$$$$$$)
{
    my $type = shift;
    my $section = shift;
    my $book = shift;
    my $file = shift;
    #my $file_node = shift;
    my $href = shift;
    my $cross_ref = shift;
    my $args_texi = shift;
    my $formatted_args = shift;
    my $node = shift;

    my $name = $section;
    $name = $cross_ref if ($name eq '');
    $name = $node if ($name eq '');

    my $reference = $name;

    if ($book eq '' and $file ne '')
    {
       $name = "($file)$name";
    }
    $reference = &$anchor('', $href, $name) if ($href ne '');

    # Yes, this is ugly, yet this helps internationalization
    if ($type eq 'pxref')
    {
         if (($book ne '') and ($href ne ''))
         {
              return gdt('see {reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif (($book ne '') and ($reference ne ''))
         {
              return gdt('see `{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif ($book ne '')
         { # should seldom or even never happen
              return gdt('see @cite{{book}}', { 'book' => $book },{'duplicate'=>1});
         }
         elsif ($href ne '')
         {
              return gdt('see {reference}', { 'reference' => $reference },{'duplicate'=>1});
         }
         elsif ($reference ne '')
         {
              return gdt('see `{section}\'', { 'section' => $reference },{'duplicate'=>1});
         }
    }
    if ($type eq 'xref' or $type eq 'inforef')
    {
         if (($book ne '') and ($href ne ''))
         {
              return gdt('See {reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif (($book ne '') and ($reference ne ''))
         {
              return gdt('See `{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif ($book ne '')
         { # should seldom or even never happen
              return gdt('See @cite{{book}}', { 'book' => $book },{'duplicate'=>1});
         }
         elsif ($href ne '')
         {
              return gdt('See {reference}', { 'reference' => $reference },{'duplicate'=>1});
         }
         elsif ($reference ne '')
         {
              return gdt('See `{section}\'', { 'section' => $reference },{'duplicate'=>1});
         }
    }
    if ($type eq 'ref')
    {
         if (($book ne '') and ($href ne ''))
         {
              return gdt('{reference} in @cite{{book}}', { 'reference' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif (($book ne '') and ($reference ne ''))
         {
              return gdt('`{section}\' in @cite{{book}}', { 'section' => $reference, 'book' => $book },{'duplicate'=>1});
         }
         elsif ($book ne '')
         { # should seldom or even never happen
              return gdt('@cite{{book}}', { 'book' => $book },{'duplicate'=>1});
         }
         elsif ($href ne '')
         {
              return gdt('{reference}', { 'reference' => $reference },{'duplicate'=>1});
         }
         elsif ($reference ne '')
         {
              return gdt('`{section}\'', { 'section' => $reference },{'duplicate'=>1});
         }
    }
    return '';
}

# format a reference to a node or a section in the generated manual. This 
# produces a full reference with introductive words and the reference itself.
#
# arguments:
# type of the reference: xref (reference at the beginning of a sentence),
#     pxref (reference in a parenthesis),  
# href linking to the html page containing the node or the section. A typical
#     use for this href is a href attribute in an <a> element
# short name for this reference
# name for this reference
# boolean true if the reference is a reference to a section
# 
# SHORT_REF should be used.
sub t2h_default_internal_ref($$$$$$$$)
{
    my $type = shift;
    my $href = shift;
    my $short_name = shift;
    my $name = shift;
    my $is_section = shift;
    my $args_texi = shift;
    my $formatted_args = shift;
    my $element = shift;

    if (! get_conf('SHORT_REF'))
    {
        $name = &$anchor('', $href, $name);
        if ($type eq 'pxref')
        {
            return gdt('see section {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section);
            return gdt('see {reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
        elsif ($type eq 'xref' or $type eq 'inforef')
        {
            return gdt('See section {reference_name}', { 'reference_name' => $name },{'duplicate'=>1}) if ($is_section);
            return gdt('See {reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
        elsif ($type eq 'ref')
        {
            return gdt('{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
    }
    else
    {
        $name = &$anchor('', $href, $short_name);
        if ($type eq 'pxref')
        {
            return gdt('see {reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
        elsif ($type eq 'xref' or $type eq 'inforef')
        {
            return gdt('See {reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
        elsif ($type eq 'ref')
        {
            return gdt('{reference_name}', { 'reference_name' => $name },{'duplicate'=>1});
        }
    }
    return '';
}

# text after @item in table, vtable and ftable
sub t2h_default_table_item($$$$$$$)
{
    my $text = shift;
    my $index_label = shift;
    my $format = shift;
    my $command = shift;
    my $style_stack = shift;
    my $item_cmd = shift;
    my $formatted_index_entry = shift;

    return $text . "\n";
}

# format text on the line following the @item line (in table, vtable and ftable)
sub t2h_default_table_line($$$)
{
    my $text = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

    if ($text =~ /\S/)
    {
        return $text;
    }
    return '';
}

#my $cell_nr = -1;

# row in multitable
sub t2h_default_row($$$$$$$$)
{
    my $text = shift;
    my $macro = shift;
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $column_number = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

    if ($text =~ /\S/)
    {
         return $text ."\n";
    }
    return '';
}

# cell in multitable
sub t2h_default_cell($$$$$$$$)
{
    my $text = shift;
    my $row_macro = shift;
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $column_number = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

    $text =~ s/^\s*//;
    $text =~ s/\s*$//;

    return " $text";
}

# format an itemize, enumerate or @*table @item line, returning
# a texinfo line.
sub t2h_default_format_list_item_texi($$$$$)
{
    my $format = shift;
    my $line = shift;
    my $prepended = shift;
    my $command = shift;
    my $number = shift;

    my $result_line;
    my $open_command = 0;

    $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize');
    $prepended = "\@$command\{\}" if (defined($command) and $command ne '');
    $prepended = "$number." if (defined($number) and $number ne '');

    if (defined($command) and $command ne '' and $format ne 'itemize')
    {
        #@*table
        $open_command = 1;
        $line =~ s/^\s*//;
        $line =~ s/\s*$//;
        if (exists ($style_map{$command}))
        {
           $result_line = "\@$command\{$line\}\n";
        }
        elsif (exists ($things_map{$command}))
        {
           $result_line = "\@$command\{\} $line\n";
        }
        else
        {
           $result_line = "\@$command $line\n";
        }
    }
    elsif (defined($prepended) and $prepended ne '')
    {
         $prepended =~ s/^\s*//;
         $prepended =~ s/\s*$//;
         $line =~ s/^\s*//;
         $result_line = $prepended . ' ' . $line;
    }
    return ($result_line, $open_command);
}


# format an item in a list
#
# argument:
# text of the item
# format of the list (itemize or enumerate)
# command passed as argument to the format
# formatted_command leading command formatted, if it is a thing command
sub t2h_default_list_item($$$$$$$$$$$$)
{
    my $text = shift;
    my $format = shift;
    my $command = shift;
    my $formatted_command = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $prepended = shift;
    my $prepended_formatted = shift;
    my $only_inter_item_commands = shift;
    my $before_items = shift;
    my $item_command = shift;

    $only_inter_item_commands = '' if (!defined($only_inter_item_commands));

    if ($text =~ /\S/)
    {
        return $text;
    }
    return '';
}

sub t2h_default_table_list($$$$$$$$$)
{
    my $format_command = shift;
    my $text = shift;
    my $command = shift;
    my $formatted_command = shift;
# enumerate
    my $item_nr = shift;
    my $enumerate_style = shift;
# itemize
    my $prepended = shift;
    my $prepended_formatted = shift;
# multitable
    my $columnfractions = shift;
    my $prototype_row = shift;
    my $prototype_lengths = shift;
    my $column_number = shift;
#    my $number = shift;
    return $text;
}

# an comment
sub t2h_default_comment($)
{
    my $text = shift;
    return '';
}

# an xml comment
sub xml_default_comment($)
{
    my $text = shift;
    $text =~ s/--+/-/go;
    return '<!-- ' . $text . ' -->' . "\n";
}

sub t2h_collect_styles($)
{
    my $cmd_stack = shift;
    my @result = ();
    foreach my $style (reverse(@$cmd_stack))
    {
#        last unless (defined($command_type{$style}) and $command_type{$style} eq 'style');
        push @result, $style if (defined($command_type{$style}) and $command_type{$style} eq 'style');
    }
    return @result;
}

sub html_default_parse_attribute($)
{
    my $element = shift;
    return ('', '', '') if (!defined($element));
    my ($class, $attributes) = ('', '');
    if ($element =~ /^(\w+)(\s+.*)/)
    {
        $element = $1;
        $attributes = $2;
        if ($attributes =~ s/^\s+class=\"([^\"]+)\"//)
        {
            $class = $1;
        }
    }
    return ($element, $class, $attributes);
}

sub t2h_get_attribute($;$)
{
    my $command = shift;
    my $map_ref = shift;
    $map_ref = \%style_map if (!defined($map_ref));
    return  unless (defined($map_ref->{$command}));
    my ($element, $class, $attributes) = ('', '', '');
    if (defined($map_ref->{$command}))
    {
        if (ref($map_ref->{$command}) eq 'HASH') 
        {
            ($element, $class, $attributes) = t2h_html_parse_attribute ($map_ref->{$command}->{'attribute'});
        }
        elsif ($map_ref->{$command} !~ /^&/)
        {
            $element = $map_ref->{$command};
            $element =~ s/^\"//;
        }
    }
    return ($element, $class, $attributes);
}

# a paragraph
# arguments:
# $text of the paragraph
# $align for the alignement
# $indent for the indent style (indent or noindent)
# The following is usefull if the paragraph is in an itemize.
# $paragraph_command is the leading formatting command (like @minus)
# $paragraph_command_formatted is the leading formatting command formatted
# $paragraph_number is a reference on the number of paragraphs appearing
#    in the format. The value should be increased if a paragraph is done
# $format is the format name (@itemize)
sub t2h_default_paragraph($$$$$$$$$$$$)
{
    my $text = shift;
    my $align = shift;
    my $indent = shift;
    my $paragraph_command = shift;
    my $paragraph_command_formatted = shift;
    my $paragraph_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $command_stack_at_end = shift;
    my $command_stack_at_begin = shift;
#print STDERR "format: $format\n" if (defined($format));
#print STDERR "paragraph @$command_stack_at_end; @$command_stack_at_begin\n";
#    $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or 
#          exists($special_list_commands{$format}->{$paragraph_command}));
    return '' if ($text =~ /^\s*$/);

    return $text;
}

# a preformatted region
# arguments:
# $text of the preformatted region
# $pre_style css style
# $class identifier for the preformatted region (example, menu-comment)
# The following is usefull if the preformatted is in an itemize.
# $leading_command is the leading formatting command (like @minus)
# $leading_command_formatted is the leading formatting command formatted
# $preformatted_number is a reference on the number of preformatteds appearing
#    in the format. The value should be increased if a preformatted is done
sub t2h_default_preformatted($$$$$$$$$$$$)
{
    my $text = shift;
    my $pre_style = shift;
    my $class = shift;
    my $leading_command = shift;
    my $leading_command_formatted = shift;
    my $preformatted_number = shift;
    my $format = shift;
    my $item_nr = shift;
    my $enumerate_style = shift;
    my $number = shift;
    my $command_stack_at_end = shift;
    my $command_stack_at_begin = shift;

#print STDERR "preformatted @$command_stack_at_end; @$command_stack_at_begin\n";
    return '' if ($text eq '');

    my $top_stack = '';
    $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
    if ($top_stack eq 'multitable')
    {
       $text =~ s/^\s*//;
       $text =~ s/\s*$//;
    }

    # add a new line at the end in case there is none
    chomp($text);
    return $text . "\n";
}

# $new_element is set if the element is associated with a different
# reference element than the preceding element. This is where we
# do the navigation. For example it could be a @node before a @section.
#
# The heading function is always called, though  -- in the default case
# nodes don't lead to an outputted title.
sub t2h_default_element_heading($$$$$$$$$$$$)
{
    my $element = shift;
    my $command = shift;
    my $texi_line = shift;
    my $line = shift;
    my $in_preformatted = shift;
    my $one_section = shift;
    my $element_heading = shift;
    my $first_in_page = shift;
    my $is_top = shift;
    my $previous_is_top = shift;
    my $command_line = shift;
    my $element_id = shift;
    my $new_element = shift;
#print STDERR ":::::::: $element $command i_p $in_preformatted o_s $one_section e_h $element_heading f_p $first_in_page i_t $is_top p_i_t $previous_is_top id $element_id new $new_element\n";

#    my $result = '';
    my $result = &$element_label($element_id, $element, $command, $command_line);

    # in default case, print_head_navigation and print_navigation are no-ops.
    # and $print_element_header is undef, so the following nothing.
    if ($new_element and !$one_section)
    {
       main::msg_debug ("For $element->{'texi'}, element_ref not defined", $element->{'line_nr'}) if (!defined($element->{'element_ref'}));
       if (!defined($element->{'element_ref'}->{'top'}))
       {
           if (defined($print_element_header))
           { # FIXME backward compatibility, print_element_header is obsoleted in nov 2009
                $result .= &$print_element_header($first_in_page, $previous_is_top);
           }
           else
           {
               if (($first_in_page or $previous_is_top) and get_conf('HEADERS'))
               {
                   $result .= &$print_head_navigation(undef, \@SECTION_BUTTONS, $first_in_page, $previous_is_top, $element);
               }
               else
               { # got to do this here, as it isn't done otherwise sinc 
                 # print_head_navigation is not called
                    $result .= &$print_navigation(\@SECTION_BUTTONS) if (get_conf('HEADERS') or get_conf('SPLIT') eq 'node');
               }
           }
       }
       else
       { # this is here because we want to always print the head navigation for top
         # and use TOP_BUTTONS
           $result .= &$print_head_navigation(undef, \@TOP_BUTTONS, $first_in_page, $previous_is_top, $element) 
              if (get_conf('SPLIT') or get_conf('HEADERS'));
       }
    }
    return $result. &$heading($element, $command, $texi_line, $line, $in_preformatted, $one_section, $element_heading);
}

# This function formats a heading for an element
#
# argument:
# an element. It is a hash reference for a node or a sectioning command.
#             it may be the wrong one in case of headings.
# The interesting keys are:
# 'text': the heading text
# 'text_nonumber': the heading text without section number
# 'node': true if it is a node
# 'level': level of the element. 0 for @top, 1 for chapter, heading, 
#      appendix..., 2 for section and so on...
# 'tag_level': the sectioning element name, raisesections and lowersections
#      taken into account
sub t2h_default_heading($$$$$;$$)
{
    my $element = shift;
    my $command = shift;
    my $texi_line = shift;
    my $line = shift;
    my $in_preformatted = shift;
    my $one_section = shift;
    my $element_heading = shift;

    my $level = $element->{'level'};
    if ($element->{'node'})
    {
        if ($element->{'text'} =~ /^top$/i)
        {
          $level = 0;
        }
        else
        {
          $level = 3;
        }
        return '' if (!$element->{'this'} or $element->{'with_section'})
    }
    else
    {
        $command = $element->{'tag_level'};
    }
    my $text = $element->{'text'};

    if (get_conf('TOC_LINKS') and $command !~ /heading/ and defined($element->{'tocid'}))
    {
         $text = &$anchor ('', "$Texi2HTML::THISDOC{'toc_file'}#$element->{'tocid'}", $text);
    }

    my $result;
    if ($in_preformatted)
    {
        $result = &$heading_text_preformatted("\@$command", $text, $level);
    }
    else
    {
        $result = &$heading_text("\@$command", $text, $level);
    }
   #$result .= "\n";
   return $result;
}

sub t2h_default_heading_no_texi($$$)
{
    my $element = shift;
    my $command = shift;
    my $line = shift;
    return main::remove_texi($line) . "\n";
}

# formatting of raw regions
# if L2H is true another mechanism is used for tex
sub t2h_default_raw($$;$)
{
    my $style = shift;
    my $text = shift;
    my $line_nr = shift;
    my $expanded = 1 if (grep {$style eq $_} @EXPAND);
    if ($style eq 'verbatim' or $style eq 'verbatiminclude' or ($style eq 'tex' and $expanded))
    {
        return $text;
    }
    elsif ($expanded)
    {
        main::line_warn (sprintf(__("Raw format %s is not converted"), $style), $line_nr);
        return $text;
    }
    else
    {
        return '';
    }
}

# raw environment when removing texi (in comments) 
sub t2h_default_raw_no_texi($$)
{
    my $style = shift;
    my $text = shift;
    if ($style eq 'verbatim' or $style eq 'verbatiminclude' or grep {$style eq $_} @EXPAND)
    {
       return $text;
    }
    return '';
}

# This function formats a footnote reference and the footnote text associated
# with a given footnote.
# The footnote reference is the text appearing in the main document pointing
# to the footnote text.
#
# arguments:
# absolute number of the footnote (in the document)
# relative number of the footnote (in the page)
# identifier for the footnote
# identifier for the footnote reference in the main document
# main document file
# footnote text file
# array with the footnote text lines 
# the state. See menu entry.
#
# returns:
# reference on an array containing the footnote text lines which should
#     have been updated
# the text for the reference pointing on the footnote text
sub t2h_default_foot_line_and_ref($$$$$$$$$)
{
    my $number_in_doc = shift;
    my $number_in_page = shift;
    my $footnote_id = shift;
    my $place_id = shift;
    my $document_file = shift;
    my $footnote_file = shift;
    my $lines = shift;
    my $document_state = shift;

    $number_in_doc = $NO_NUMBER_FOOTNOTE_SYMBOL if (!get_conf('NUMBER_FOOTNOTES'));
    
    if ($document_file eq $footnote_file)
    {
        $document_file = $footnote_file = '';
    }
    unshift (@$lines, "($number_in_doc)\n");
    push @$lines, "\n";
    return ($lines, "($number_in_doc)");
}

# formats a group of footnotes.
#
# argument:
# array reference on the footnotes texts lines 
#
# returns an array reference on the group of footnotes lines
sub t2h_default_foot_section($)
{
    my $lines = shift;
    my $header = &$heading_text('footnotes', gdt('Footnotes'), 3);
    unshift (@$lines, "$header\n");
    return $lines; 
}

sub t2h_default_image_files($$$$)
{
    my $base = shift;
    my $extension = shift;
    my $texi_base = shift;
    my $texi_extension = shift;
    my @files = ();
    return @files if (!defined($base) or ($base eq ''));
    if (defined($extension) and ($extension ne ''))
    {
       push @files,["$base.$extension", "$texi_base.$texi_extension"];
    }
    foreach my $ext (@IMAGE_EXTENSIONS)
    {
        push @files,["$base.$ext", "$texi_base.$ext"];
    }
    return @files;
}

# format an image
#
# arguments:
# image file name with path
# image basename
# a boolean true if we are in a preformatted format
# image file name without path
# alt text
# width
# height
# raw alt
# extension
# path to working dir
# path to file relative from working dir
sub t2h_default_image($$$$$$$$$$$$$$$$$)
{
    my $file = shift;
    my $base = shift;
    my $preformatted = shift;
    my $file_name = shift;
    my $alt = shift;
    my $width = shift;
    my $height = shift;
    my $raw_alt = shift;
    my $extension = shift;
    my $working_dir = shift;
    my $file_path = shift;
    my $in_paragraph = shift;
    my $file_locations = shift;
    my $base_simple_format = shift;
    my $extension_simple_format = shift;
    my $file_name_simple_format = shift;
    my $line_nr = shift;
 
    if (!defined($file_path) or $file_path eq '')
    {
        if (defined($extension) and $extension ne '')
        {
            $file = "$base.$extension";
        }
        else
        {
            $file = "$base.txt";
        }
    }
    elsif (! get_conf('COMPLETE_IMAGE_PATHS'))
    {
        $file = $file_name;
    }
    my $alt_txt = '';
    $alt_txt = ": $alt" if (defined($alt) and $alt =~ /\S/);
    return "[ $file$alt_txt ]";
    # it is possible that $file_name is more correct as it allows the user
    # to chose the relative path.
}

# address put in footer describing when was generated and who did the manual
# not used anymore
sub t2h_default_address($)
{
    my $date = shift;
    $date = '' if (!defined($date));
    if ($date ne '')
    {
        return gdt('on @emph{{date}}', { 'date' => $date });
    }
    return '';
}

# format a target in the main document for an index entry.
#
# arguments:
# target identifier
# boolean true if in preformatted format
sub t2h_default_index_entry_label($$$$$$$$$)
{
    my $identifier = shift;
    my $preformatted = shift;
    my $entry = shift;
    my $index_name = shift;
    my $index_command = shift;
    my $texi_entry = shift;
    my $formatted_entry = shift;
    my $in_region_not_in_output = shift;
    my $index_entry_ref = shift;

    return '' if (!defined($identifier) or ($identifier !~ /\S/));
    my $label = &$anchor($identifier);
    return $label;
}

sub t2h_default_index_entry_command($$$$$$)
{
   my $command = shift;
   my $index_name = shift;
   my $label = shift;
   my $entry_texi = shift;
   my $entry_formatted = shift;
   my $index_entry_ref = shift;

   return $label;
}

# process definition commands line @deffn for example
sub t2h_default_def_line($$$$$$$$$$$$$$$$)
{
   my $category_prepared = shift;
   my $name = shift;
   my $type = shift;
   my $arguments = shift;
   my $index_label = shift;
   my $arguments_array = shift;
   my $arguments_type_array = shift;
   my $unformatted_arguments_array = shift;
   my $command = shift;
   my $class_name = shift;
   my $category = shift;
   my $class = shift;
   my $style = shift;
   my $original_command = shift;

   $name = '' if (!defined($name) or ($name =~ /^\s*$/));
   $type = '' if (!defined($type) or $type =~ /^\s*$/);
   $arguments = '' if (!defined($arguments) or $arguments =~ /^\s*$/);

   my $type_name = '';
   $type_name .= "$type " if ($type ne '');
   $type_name .= $name if ($name ne '');

   my $result = " -- $category_prepared: ${type_name}$arguments";
   $result =~ s/\s*$//;
   $result .= "\n";

}

# process definition commands line @deffn for example while removing texi
# commands
sub t2h_default_def_line_no_texi($$$$$)
{
   my $category = shift;
   my $name = shift;
   my $type = shift;
   my $arguments = shift;
   $name = '' if (!defined($name) or ($name =~ /^\s*$/));
   $type = '' if (!defined($type) or $type =~ /^\s*$/);
   if (!defined($arguments) or $arguments =~ /^\s*$/)
   {
       $arguments = '';
   }
   my $type_name = '';
   $type_name = " $type" if ($type ne '');
   $type_name .= ' ' . $name if ($name ne '');
   $type_name .= $arguments;
   if (! get_conf('DEF_TABLE'))
   {
       return $category . ':' . $type_name . "\n";
   }
   else
   {
       
       return $type_name . "    " . $category . "\n";
   }
}

# a cartouche
sub t2h_default_cartouche($$)
{
    my $text = shift;

    if ($text =~ /\S/)
    {
        return $text;
    }
    return '';
} 

my $IDXFILE;
# key:          
# origin_href:  
# entry:        
# texi entry: 
# element_href: 
# element_text: 
sub t2h_default_index_summary_file_entry ($$$$$$$$$)
{
    my $index_name = shift;
    my $key = shift;
    my $origin_href = shift;
    my $entry = shift;
    my $texi_entry = shift;
    my $element_href = shift;
    my $element_text = shift;
    my $is_printed = shift;
    my $manual_name = shift;

    $element_text = 'UNDEF' if (!defined($element_text));
    print $IDXFILE "key: $key\n  origin_href: $origin_href\n  entry: $entry\n"
      . "  texi_entry: $texi_entry\n"
      . "  element_href: $element_href\n  element_text: $element_text\n";
}

sub t2h_default_index_summary_file_begin($$$)
{
    my $name = shift;
    my $is_printed = shift;
    my $manual_name = shift;

    $IDXFILE = main::open_out("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'file_base_name'}" . "_$name.idx");
}

sub t2h_default_index_summary_file_end($$$)
{
    my $name = shift;
    my $is_printed = shift;
    my $manual_name = shift;

    close ($IDXFILE);
}

sub t2h_default_sp($$)
{
   my $number = shift;
   my $preformatted = shift;
   return "\n" x $number;
}

sub t2h_default_acronym_like($$$$$$)
{
    my $command = shift;
    my $acronym_texi = shift;
    my $acronym_text = shift;
    my $with_explanation = shift;
    my $explanation_lines = shift;
    my $explanation_text = shift;
    my $explanation_simply_formatted = shift;
    
   if ($with_explanation)
   {
       #return "$acronym_text ($explanation_text)";
       return gdt('{acronym_like} ({explanation})', {'acronym_like' => $acronym_text, 'explanation' => $explanation_text},{'duplicate'=>1});
   }
   else
   {
       return "$acronym_text";
   }

}

sub t2h_default_quotation_prepend_text($$)
{
    my $command = shift;
    my $text = shift;
    return undef if (!defined($text) or $text =~ /^$/);
    # If there is a @ protecting the end of line the result is, 
    # after the chomp:
    # @b{some text @:}
    # It is likely not to be what was intended, but it is certainly right.
    # this is tested in formatting/quotation.texi
    chomp($text);
    return gdt('@b{{quotation_arg}:} ', {'quotation_arg' => $text}, {'keep_texi' => 1});
}

sub t2h_default_quotation($$$$$)
{
    my $command = shift;
    my $text = shift;
    my $argument_text = shift;
    my $argument_text_texi = shift;
    my $authors = shift;
    my $class_text = '';
    # this allows to add an end of line if there was none, which can happen 
    # if there is an argument to @quotation, but an empty quotation, like
    # @quotation something
    # @end quotation
    chomp($text);
    $text .= "\n";
    return $text;
}

# format the text within a paragraph style format,
#
# argument:
# format name
# text within the format
sub t2h_default_paragraph_style_command($$)
{
    my $format = shift;
    my $text = shift;
    return $text;
}

# format a whole index
#
# argument:
# index text
# index name
sub t2h_default_print_index($$)
{
    my $text = shift;
    my $name = shift;
    return '' if (!defined($text));
    return "* Index:\n" . $text;
}

# format a letter entry in an index page. The letter entry contains
# the index entries for the words beginning with that letter. It is 
# a target for links pointing from the summary of the index.
#
# arguments:
# the letter
# identifier for the letter entry. This should be used to make the target
#     identifier
# text of the index entries
sub t2h_default_index_letter($$$)
{
     my $letter = shift;
     my $id = shift;
     my $text = shift;
     return $text;
}

# format an index entry (in a letter entry).
#
# arguments:
# href to the main text, linking to the place where the index entry appears
# entry text
# href to the main text, linking to the section or node where the index 
#      entry appears
# section or node heading
sub t2h_default_index_entry($$$$$$$$$$)
{
    my $text_href = shift;
    my $entry = shift;
    my $element_href = shift;
    my $element_text = shift;
    my $entry_file = shift;
    my $current_element_file = shift;
    my $entry_target = shift;
    my $entry_element_target = shift;
    my $in_region_not_in_output = shift;
    my $index_entry_ref = shift;
    
    return '' if ($in_region_not_in_output);
    #!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'}));
    my $state = {};
    $state = { 'code_style' => 1 } if ($index_entry_ref->{'in_code'});
    $entry = main::substitute_line($index_entry_ref->{'texi'}, "index entry in \@printindex", $state);
    return '' if ($entry =~ /^\s*$/);

    my $real_element_text;
    my $element = $index_entry_ref->{'real_element'};
    # in case $element->{'text'} is not defined, it certainly means that we
    # are n a special elemet, most likely the virtual element appearing 
    # before anything else
    if (defined($element->{'text'}))
    {
       my $element_set = 0;
       if (get_conf('NODE_NAME_IN_INDEX'))
       {
           if ($element->{'node'})
           {
               $element_set = 1;
           }
           elsif ($element->{'with_node'})
           {
               $element = $element->{'with_node'};
               $element_set = 1;
           }
       }
       elsif (defined(get_conf('NODE_NAME_IN_INDEX')))
       {
           if (!$element->{'node'})
           {
               $element_set = 1;
           }
           elsif ($element->{'with_section'})
           {
               $element = $element->{'with_section'};
               $element_set = 1;
           }
       }
       $element = $element->{'element_ref'} if ($element->{'element_ref'} and !$element_set);
       $real_element_text = $element->{'text'};
    }
    else
    {
       $real_element_text = gdt('(outside of any element)');
    }
    return "* $entry: ".$real_element_text . '.'."\n";
}


sub t2h_default_copying_comment($$$$)
{
    my $copying_lines = shift;
    my $copying_text = shift;
    my $copying_no_texi = shift;
    my $copying_simple_text = shift;
    return '' if ($copying_no_texi eq '');
    my $text = &$comment($copying_no_texi);
    return $text;
}

# return value is currently ignored
sub t2h_default_documentdescription($$$$)
{
    my $decription_lines = shift;
    my $description_text = shift;
    my $description_no_texi = shift;
    my $description_simple_text = shift;

    #return '' if ($description_no_texi eq ''); 
    #my @documentdescription = split (/\n/, $description_no_texi);
    if ($description_simple_text eq '')
    {
        set_from_document('documentdescription', undef);
        return;
    }
    my @documentdescription = split (/\n/, $description_simple_text);
    my $document_description = shift @documentdescription;
    chomp $document_description;
    foreach my $line (@documentdescription)
    {
        chomp $line;
        $document_description .= ' ' . $line;
    }
    set_from_document('documentdescription', $document_description);
}

# format an index summary. This is a list of letters linking to the letter
# entries.
#
# arguments:
# array reference containing the formatted alphabetical letters
# array reference containing the formatted non lphabetical letters
sub t2h_default_index_summary($$)
{
    my $alpha = shift;
    my $nonalpha = shift;

    my $join = '';
    my $nonalpha_text = '';
    my $alpha_text = '';
    return '';
}

# return the heading with number texinfo text
# also called for nodes.
sub t2h_default_heading_texi($$$)
{
    my $tag = shift;
    my $texi = shift;
    my $number = shift;
    #$texi = main::trim_around_spaces($texi);
    return "$number $texi" if (get_conf('NUMBER_SECTIONS') and defined($number) and ($number !~ /^\s*$/)) ;
    return $texi;
}

# return the heading texinfo text for split index sections
sub t2h_default_index_element_heading_texi($$$)
{ # FIXME i18n
    my $heading_texi = shift;
    my $tag = shift;
    my $texi = shift;
    my $number = shift;
    my $first_letter = shift;
    my $last_letter = shift;
    return "$heading_texi: $first_letter -- $last_letter" if ($last_letter ne $first_letter);
    return "$heading_texi: $first_letter";
}

sub t2h_default_element_label($$$$)
{
    my $id = shift;
    my $element = shift;
    my $command = shift;
    my $line = shift;

    return &$anchor($id);
}

sub t2h_default_misc_element_label($$)
{
    my $id = shift;
    my $misc_page_name = shift;
    return &$anchor($id);
}

sub t2h_default_anchor_label($$$$)
{
    my $id = shift;
    my $anchor_text = shift;
    my $anchor_reference = shift;
    my $in_special_region = shift;
    return &$anchor($id);
}

sub t2h_default_colon_command($)
{
   my $punctuation_character = shift;
   return $colon_command_punctuation_characters{$punctuation_character} if defined($colon_command_punctuation_characters{$punctuation_character});
   return $punctuation_character;
}

# called each time a @tab or an @itemx is encountered.
# To be noticed that there is another function better suited for 
# formatting of an @item line: $format_list_item_texi
sub t2h_default_tab_item_texi($$$$$$)
{
   my $command = shift;
   my $commands_stack = shift;
   my $stack = shift;
   my $state = shift;
   my $line = shift;
   my $line_nr = shift;

   return undef;
}

sub xml_default_line_command($$$$)
{
    my $command = shift;
    my $arg_text = shift;
    my $arg_texi = shift;
    my $state = shift;

    my $style = $line_command_map{$command};
    return '' if ($arg_text eq '' and !defined($style) or $style eq '');
    if ($style)
    {
        my $attribute_text = '';
        if ($style =~ /^(\w+)(\s+.*)/)
        {
            $style = $1;
            $attribute_text = $2;
        }
        $arg_text = "<${style}$attribute_text>$arg_text</$style>";
    }
    $arg_text .= "\n";
    return $arg_text;
}

sub t2h_default_line_command($$$$)
{
    my $command = shift;
    my $arg_text = shift;
    my $arg_texi = shift;
    my $state = shift;

    return $arg_text;
}

# info is special, since it doesn't use the basename but directly the 
# setfilename output, contrary to all the other formats
sub t2h_default_element_file_name($$$)
{
    my $element = shift;
    my $type = shift;
    my $prefix = shift;

    my $outname;
    return unless (get_conf('USE_SETFILENAME_EXTENSION') and get_conf('PREFIX') eq '');
    my $outfile = get_conf('OUTFILE');
    $outname = $outfile if (defined($outfile) and $outfile ne '' and $Texi2HTML::THISDOC{'input_file_number'} == 0);
    if ($type eq 'doc' or !get_conf('SPLIT'))
    {
       if (defined(get_conf('setfilename')) and !defined($outname))
       {
          main::document_override('EXTENSION', '');
          return get_conf('setfilename');
       }
    }

    return undef;
}

sub t2h_default_misc_command_line($$$$$)
{
   my $macro = shift;
   my $line = shift;
   my $args = shift;
   my $stack = shift;
   my $state = shift;
   
   my $result;
   return ($macro, $line, $result);
}

sub t2h_default_internal_links($$$)
{
  my $fh = shift;
  my $elements_list = shift;
  my $indices = shift;
  
  foreach my $element (@$elements_list)
  {
     my $text = $element->{'no_texi'};
     #$text =~ s/^([\w.]+)\. /$1 /;
     #$text = "Annexe ".$text if ($element->{'tag'} =~ /appendix/);
     print $fh "$element->{'file'}#$element->{'id'}\ttoc\t$text\n";
  }
  foreach my $index_name (sort(keys(%$indices)))
  {
     my $entries = $indices->{$index_name};
     
     foreach my $letter_entries (@$entries)
     {
       foreach my $entry (@{$letter_entries->{'entries'}})
       {
        #print STDERR "($index_name) key $key, t $entry->{'texi'}: $entry->{'file'}#$entry->{'target'}\n";
        print $fh "$entry->{'file'}#$entry->{'target'}\t$index_name\t$entry->{'key'}\n" if ($entry->{'key'} =~ /\S/);
       }
     }
  }
}

1;
